我有一个文本文件,其中包含数百万个索引点,这些索引点都被解释为字符串,并且用制表符分隔。但是,某些索引点可能会丢失。这是我的文本文件的示例:
var result = Speach.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Select(x => Regex.Replace(x.ToLower(), "[^a-zA-Z0-9-]", ""))
.GroupBy(x => x)
.ToDictionary(x => x.Key, x => x.Count());
Print(result.OrderByDescending(x => x.Value).ToList());
请注意,第4、6和8行丢失。我的目标是创建一个可以解析文本文件,识别可能缺少的索引点并返回包含所有缺少的索引点(如果有)或不返回任何内容的列表的函数。
我在Spyder IDE Windows10操作系统中使用Python 3.7。我对Python和Stackoverflow比较陌生。
这是我到目前为止所掌握的。这适用于ID 1缺少索引,但是如果缺少几个索引点,则失败。
错误从第一行else开始。我不确定如何使用for循环的索引(0、1、2、3 ...)跟踪文档(1、2、3、5 ...)中观察到的索引,因为随着时间的推移缺少索引点。
请注意,文本文档的前4行包含标头信息,我在解析过程中忽略了标头信息,这就是为什么data = f.readlines()[4:]
1 0 4 0d 07:00:37.0400009155273
2 0 4 0d 07:00:37.0400009155273
3 0 4 0d 07:00:37.0400009155273
5 0 4 0d 07:00:37.0400009155273
7 0 4 0d 07:00:37.0400009155273
9 0 4 0d 07:00:37.0400009155273
...
感谢所有帮助!
答案 0 :(得分:1)
您可以单独使用Python做到这一点:
with open(filename) as f:
indices = [int(row.split('\t')[0]) for row in f.read().split('\n')[4:]]
missing_indices = [index
for index in range(1, len(indices) + 1)
if index not in indices]
这会将您的数据转换为嵌套的list
,其中每个外部list
包含一行,每个内部list
包含一个元素。由于我们只关心索引,因此我们得到第一个元素而忽略其他元素。
然后,由于索引按从1开始的运行顺序,我们构造了一个{<1>}跨越索引的 expected 范围,并获取存在于该范围但不存在于该范围内的索引文件。
假设索引是唯一的(这似乎是合理的),我们还可以使用 DYZ 的建议使用range
:
sets
missing_indices = set(range(1, len(indices) + 1) - set(indices)
也可以正常工作:
pandas
这将从您的数据中创建一个import pandas as pd
df = pd.read_csv(filename, sep='\t').iloc[4:]
range_index = pd.RangeIndex(1, len(df) + 1)
print(range_index[~range_index.isin(df.iloc[:, 0])]
DataFrame,并切断了前四行。遵循与其他答案相同的原理,它创建一个具有所有期望值的索引,并获取DataFrame第一列中不存在的子集。
答案 1 :(得分:1)
另一个答案为您提供了更好的整体解决方案,但是我只是想帮助您指导给定的正确方向,以便您了解如何改变自己的工作方式:
def check_sorted_file(fileName):
missing_idx = []
last_index = 0
with open(fileName, 'r') as f:
data = f.readlines()[4:]
for line in data:
idx = int(line.split()[0])
if idx == last_index+1:
pass
else:
missing_idx.extend(list(range(last_index+1, idx)))
last_index = idx
if missing_idx:
print('\nThe following idicie(s) are missing: ')
print(*missing_idx, sep=", ")
else:
print('\nAll indices are accounted for. ')
return missing_idx
因此,无需使用枚举,我们将使用传入索引作为我们所在位置的指南。
要解决多个遗漏问题,我们使用range
获取最后一个索引和当前索引之间的所有数字,并使用新的数字集扩展列表。
答案 2 :(得分:1)
由于行数很多,您可能希望以懒惰的方式执行此操作,而无需创建大列表或使用signal
来测试每个值是否在百万行列表中。您可以混合使用一些itertools作为迭代器,并保存列表的末尾(如果您需要的话)。
基本上,您将in
和tee
做成两个迭代器以获取索引,用map
剔除其中一个的值,然后压缩它们以检查是否存在差异:< / p>
next()
结果:
from itertools import chain, tee
lines = ["1 0 4 0d 07:00:37.0400009155273",
"2 0 4 0d 07:00:37.0400009155273",
"3 0 4 0d 07:00:37.0400009155273",
"5 0 4 0d 07:00:37.0400009155273",
"7 0 4 0d 07:00:37.0400009155273",
"9 0 4 0d 07:00:37.0400009155273"
]
#two iterators going over indexes
i1, i2 = tee(map(lambda x: int(x.split()[0]), lines), 2)
# move one forward
next(i2)
# chain.from_iterable will be an iterator producing missing indexes:
list(chain.from_iterable(range(i+1, j) for i, j in zip(i1, i2) if j-i!=1))
答案 3 :(得分:0)
这是一个紧凑,健壮,基于集合的仅Python核心解决方案。读取文件,将每一行拆分为多个字段,将第一个字段转换为一个int,然后构建一组实际索引:
skip = 4 # Skip that many lines
with open(yourfile) as f:
for _ in range(skip):
next(f)
actual = {int(line.split()[0]) for line in f}
创建一组预期的索引并取差值:
expected = set(range(min(actual), max(actual) + 1))
sorted(expected - actual)
#[4, 6, 8]
即使索引不是从1开始,该解决方案仍然有效。