Tôi có ba tệp dữ liệu đầu vào. Mỗi người sử dụng một dấu phân cách khác nhau cho dữ liệu có trong đó. Tệp dữ liệu Một trông như thế này:
apples | bananas | oranges | grapes
Tệp dữ liệu hai trông như thế này:
quarter, dime, nickel, penny
Tệp dữ liệu ba trông như thế này:
horse cow pig chicken goat
[Sự thay đổi số lượng cột cũng có chủ ý]
Ý nghĩ tôi có là đếm số lượng ký tự không phải là alpha, và cho rằng số lượng cao nhất là ký tự phân tách. Tuy nhiên, các tệp có dấu phân cách không gian cũng có khoảng trống trước và sau khi phân tách, vì vậy các không gian giành chiến thắng trên cả ba tệp. Đây là mã của tôi:
def count_chars[s]:
valid_seps=[' ','|',',',';','\t']
cnt = {}
for c in s:
if c in valid_seps: cnt[c] = cnt.get[c,0] + 1
return cnt
infile = 'pipe.txt' #or 'comma.txt' or 'space.txt'
records = open[infile,'r'].read[]
print count_chars[records]
Nó sẽ in một từ điển với số lượng của tất cả các ký tự chấp nhận được. Trong mỗi trường hợp, không gian luôn chiến thắng, vì vậy tôi không thể dựa vào điều đó để cho tôi biết dấu phân cách là gì.
Nhưng tôi không thể nghĩ ra một cách tốt hơn để làm điều này.
Bất kỳ đề xuất?
hỏi ngày 17 tháng 10 năm 2010 lúc 5:19Oct 17, 2010 at 5:19
Greg Gauthiergre GauthierGreg Gauthier
1.2871 Huy hiệu vàng12 Huy hiệu bạc25 Huy hiệu đồng1 gold badge12 silver badges25 bronze badges
Nếu bạn đang sử dụng Python, tôi sẽ đề nghị gọi Re.Split trên dòng với tất cả các dấu phân cách dự kiến hợp lệ:
>>> l = "big long list of space separated words"
>>> re.split[r'[ ,|;"]+', l]
['big', 'long', 'list', 'of', 'space', 'separated', 'words']
Vấn đề duy nhất sẽ là nếu một trong các tệp sử dụng dấu phân cách như một phần của dữ liệu.
Nếu bạn phải xác định phân tách, đặt cược tốt nhất của bạn là đếm mọi thứ không bao gồm không gian. Nếu hầu như không có sự cố, thì đó có lẽ là không gian, nếu không, đó là tối đa của các ký tự được ánh xạ.
Thật không may, thực sự không có cách nào để chắc chắn. Bạn có thể có dữ liệu phân tách không gian chứa đầy dấu phẩy hoặc bạn có thể có | Dữ liệu riêng biệt chứa đầy dấu chấm phẩy. Nó có thể không phải lúc nào cũng hoạt động.
Đã trả lời ngày 17 tháng 10 năm 2010 lúc 5:24Oct 17, 2010 at 5:24
JoshdjoshdJoshD
12.2k2 Huy hiệu vàng42 Huy hiệu bạc53 Huy hiệu Đồng2 gold badges42 silver badges53 bronze badges
11
Chúng ta có thể xác định dấu phân cách phù hợp hầu hết thời gian dựa trên một số thông tin trước [chẳng hạn như danh sách các dấu phân cách phổ biến] và tính toán tần số mà tất cả các dòng cung cấp cùng một số dấu phân cách
def head[filename: str, n: int]:
try:
with open[filename] as f:
head_lines = [next[f].rstrip[] for x in range[n]]
except StopIteration:
with open[filename] as f:
head_lines = f.read[].splitlines[]
return head_lines
def detect_delimiter[filename: str, n=2]:
sample_lines = head[filename, n]
common_delimiters= [',',';','\t',' ','|',':']
for d in common_delimiters:
ref = sample_lines[0].count[d]
if ref > 0:
if all[[ ref == sample_lines[i].count[d] for i in range[1,n]]]:
return d
return ','
Thông thường n = 2 dòng là đủ, hãy kiểm tra nhiều dòng hơn để biết câu trả lời mạnh mẽ hơn. Tất nhiên có những trường hợp [thường là những trường hợp nhân tạo] dẫn đến phát hiện sai nhưng nó không thể xảy ra trong thực tế.
Ở đây tôi sử dụng triển khai Python hiệu quả của chức năng đầu chỉ đọc dòng N-First của một tệp. Xem câu trả lời của tôi về cách đọc n-lines đầu tiên của tệp
Đã trả lời ngày 8 tháng 7 năm 2021 lúc 22:38Jul 8, 2021 at 22:38
2
Cuối cùng tôi đã đi với Regex, vì vấn đề không gian. Đây là mã hoàn thành của tôi, trong trường hợp bất kỳ ai cũng quan tâm, hoặc có thể sử dụng bất cứ thứ gì khác trong đó. Trên một lưu ý tiếp tuyến, sẽ rất gọn gàng khi tìm cách xác định tự động thứ tự cột, nhưng tôi nhận ra rằng đó là một chút khó khăn hơn. Trong khi đó, tôi đang trở lại với các thủ thuật cũ để sắp xếp điều đó.
for infile in glob.glob[os.path.join[self._input_dir, self._file_mask]]:
#couldn't quite figure out a way to make this a single block
#[rather than three separate if/elifs. But you can see the split is
#generalized already, so if anyone can come up with a better way,
#I'm all ears!! :]
for row in open[infile,'r'].readlines[]:
if infile.find['comma'] > -1:
datefmt = "%m/%d/%Y"
last, first, gender, color, dobraw = \
[x.strip[] for x in re.split[r'[ ,|;"\t]+', row]]
elif infile.find['space'] > -1:
datefmt = "%m-%d-%Y"
last, first, unused, gender, dobraw, color = \
[x.strip[] for x in re.split[r'[ ,|;"\t]+', row]]
elif infile.find['pipe'] > -1:
datefmt = "%m-%d-%Y"
last, first, unused, gender, color, dobraw = \
[x.strip[] for x in re.split[r'[ ,|;"\t]+', row]]
#There is also a way to do this with csv.Sniffer, but the
#spaces around the pipe delimiter also confuse sniffer, so
#I couldn't use it.
else: raise ValueError[infile + "is not an acceptable input file."]
Đã trả lời ngày 18 tháng 10 năm 2010 lúc 15:08Oct 18, 2010 at 15:08
Greg Gauthiergre GauthierGreg Gauthier
1.2871 Huy hiệu vàng12 Huy hiệu bạc25 Huy hiệu đồng1 gold badge12 silver badges25 bronze badges
Nếu bạn đang sử dụng Python, tôi sẽ đề nghị gọi Re.Split trên dòng với tất cả các dấu phân cách dự kiến hợp lệ:
import csv
def get_delimiter[file_path: str] -> str:
with open[file_path, 'r'] as csvfile:
delimiter = str[csv.Sniffer[].sniff[csvfile.read[]].delimiter]
return delimiter
Vấn đề duy nhất sẽ là nếu một trong các tệp sử dụng dấu phân cách như một phần của dữ liệu.Aug 16 at 17:38