假设我有一个二维值列表
[[00000.ppm,11],[00001.ppm,40],[00001.ppm,38],[00001.ppm,13],00002.ppm,39],[00003.ppm,4] ]
我需要从列表的第二维中选择每个值,其中file =“anything.ppm'
所以当我搜索00001.ppm时,我会得到值“40”,“38”,“13”作为输出
此外,我需要将这些值分开,以便我可以比较它们,例如
_class=13
if (value==_class): do something
我在考虑是否还有其他方式,而不仅仅是在整个列表中进行代价高昂的循环,因为事实上 - 文件是有序的,它们的名称总是一个int增量。
我只是不知道每个文件有多少。
将.csv文件读入列表可能是个坏主意。
.csv格式
00000.ppm,11
00001.ppm,40
00001.ppm,38
00001.ppm,13
00002.ppm,39
00003.ppm,4
答案 0 :(得分:2)
我在考虑是否还有其他方式,而不仅仅是昂贵的循环 通过整个列表,因为事实上 - 文件是有序的 他们的名字总是一个int增量。
您可以利用文件对象可迭代的事实,并在从00001过渡到00002时停止读取它,而不是将整个数据集读取到列表并进行传递。
from io import BytesIO
def _read_file(file_path, encoding='utf-8'):
io_obj = BytesIO()
get(file_path, io_obj)
return io_obj.getvalue().decode(encoding)
同样,这假设0000x.ppm字段按您的问题排序。
obj.csv:
def read_partial(file, key='00001.ppm'):
with open('obj.csv') as f:
found = False
for line in f:
if line.startswith(key):
yield int(line.split(',')[-1].strip())
found = True
else:
if found:
break
>>> list(read_partial('obj.csv'))
[40, 38, 13]
如果您确实想要在列表上进行迭代,可以使用00000.ppm,11
00001.ppm,40
00001.ppm,38
00001.ppm,13
00002.ppm,39
00003.ppm,4
。
答案 1 :(得分:1)
听起来您想要获取与特定文件名对应的所有值的列表。如果你没有很多项目和/或你想要检查所有的文件名,那么最好的办法就是使用for循环将所有相关值组合在一个字典中。但是如果你有一个非常长的,排序的项目列表,并且你只想检查一些文件名,那么你可以使用bisect
模块非常快速地搜索列表。
下面的代码给出了两种方法的示例。
entries = [
['00000.ppm', 11],
['00001.ppm', 40], ['00001.ppm', 38], ['00001.ppm', 13],
['00002.ppm', 39],
['00003.ppm', 4]
]
# good for most cases:
values = dict()
for filename, value in entries:
values.setdefault(filename, []).append(value)
print(values['00001.ppm'])
# [40, 38, 13]
# not clear what you want to do with these next...
# this method searches within a sorted list.
# it will be useful if there are many items in the entries list (> ~100000)
# and you only need to lookup a few
import bisect
def find_values(entries, filename):
starting_search_key = [filename, -1]
i = bisect.bisect_left(entries, starting_search_key)
values = []
while i < len(entries) and entries[i][0] == filename:
values.append(entries[i][1])
i += 1
return values
print(find_values(entries, '00001.ppm'))
# [40, 38, 13]
或者,Pandas包可能是一个更好的全能选项,因为它可以非常快速地读取csv文件,并且可以对结果数据进行索引搜索。这里有一些代码:
import pandas as pd
entries = pd.read_csv('myfile.csv', index_col=0, names=['filename', 'class'])
print(list(entries.loc['00001.ppm', 'class']))
如果您有一个巨大的csv文件并且只需要进行一些搜索,那么您可以使用二分算法快速搜索而无需读取大部分文件。但是你可能不得不自己实现算法,而不是使用bisect模块。你必须打开文件,然后使用file.seek()
跳到中间,然后向前扫描直到你回车,然后检查下一个文件名是否小于你的文件名。求。如果是这样的话,向前跳一半;如果没有,跳回去一半。重复,直到找到你感兴趣的文件名。但是这有复杂的边缘情况,除非你有一个非常大的csv文件并且需要对它进行一些搜索,否则我不会追求它。更好的选择是使用数据库和/或Dask包。
答案 2 :(得分:-1)
我认为没有办法在没有循环数组的情况下做到这一点。
您可以使用this answer中显示的方法。这里
[ i for i, word in enumerate(my_list[:][0]) if word == 'something.ppm' ]
应该为您提供数组中元素的索引。然后,您可以使用这些索引在第二列中获取相应的值:
my_list[i][1]