我正在寻找在python中创建列表的最佳方法,该列表为放入列表的对象的所有属性创建散列索引(dicts)。
>>> foo = IndexingList([{ 'id': 1, 'name': 'cat' }, { 'id': 2, 'name': 'dog' }])
>>> foo[0]
{'id': 1, 'name': 'cat'}
>>> foo.findall('id', 2)
[{'id': 2, 'name': 'dog'}]
>>> foo += {'id': 3, 'name': 'dog'}
>>> foo.findall('name', 'dog')
[{'id': 2, 'name': 'dog'}, {'id': 3, 'name': 'dog'}]
我认为IndexingList的数据结构如下所示:
{
'items': [
{ 'id': 1, 'name': 'cat' },
{ 'id': 2, 'name': 'dog' }
],
'indexes': {
'id': {
1: [{ 'id': 1, 'name': 'cat' }],
2: [{ 'id': 2, 'name': 'dog' }]
},
'name': {
'cat': [{ 'id': 1, 'name': 'cat' }],
'dog': [
{ 'id': 2, 'name': 'dog' },
{ 'id': 3, 'name': 'dog' }
]
}
}
}
“索引”节点中的对象引用“项目”中的相同对象。
我认为属于自身对象的属性值可以通过使用str(property)来获取“index”中的内容来获得唯一的索引键。
答案 0 :(得分:3)
使用某些collections.defaultdict()
实际上很容易做到 - 尽管如果你经常使用它,你可能会考虑使用实际的数据库。
from collections import defaultdict
from functools import partial
class IndexingList:
def __init__(self, items):
self.items = []
self.indices = defaultdict(partial(defaultdict, list))
self.extend(items)
def append(self, item):
try:
for index, value in item.items():
self.indices[index][value].append(item)
except AttributeError as e:
raise ValueError("All children of an IndexingList must be "
"dict-like. '{0}' is not.".format(item)) from e
self.items.append(item)
def extend(self, iterable):
for item in iterable:
self.append(item)
def __iadd__(self, other):
self.extend(other)
return self
def __getitem__(self, item):
return self.items[item]
def __setitem__(self, item, value):
self.items[item] = value
def __delitem__(self, item):
del self.items[item]
for index, value in item.items():
self.indices[index][value].remove(item)
def find_all(self, index, value):
return self.indices[index][value]
def __repr__(self):
return repr(self.items)
像这样使用:
>>> foo = IndexingList([{ 'id': 1, 'name': 'cat' }, { 'id': 2, 'name': 'dog' }])
>>> foo[0]
{'id': 1, 'name': 'cat'}
>>> foo.find_all("id", 2)
[{'id': 2, 'name': 'dog'}]
>>> foo += [{'id': 3, 'name': 'dog'}]
>>> foo.find_all('name', 'dog')
[{'id': 2, 'name': 'dog'}, {'id': 3, 'name': 'dog'}]
答案 1 :(得分:0)
我必须说Lattyware提供了一个非常好的解决方案。我仍然提供自己快速而肮脏的方法,就像在索引独特物品时它是一个简单的单线。我有时在某个列上创建一个索引,而不是构建一个好的包装容器:
my_list = [('aap', 123), ('noot', 234), ('mies', 345), ('mies', 456)]
如果该列中的键是唯一的,我们不会将任何新元素添加到列表中,也不会修改我们可能使用的索引值:
def mk_unique_index(data, col):
g = ((elem[col], elem) for elem in data)
return dict(g)
所以我们可以像:
一样使用它>>> idx = mk_unique_index(my_list, 1)
>>> idx[123]
('aap', 123)
但是,如果我们希望在第0列上编制索引,我们必须使用defaultdict
from collections import defaultdict
def mk_index(data, col):
d = defaultdict(list)
for elem in data:
d[elem[col]].append(elem)
return d
用法:
>>> idx = mk_index(my_list, 0)
>>> idx['mies']
[('mies', 345), ('mies', 456)]
如果您使用字典甚至命名元组而不是元组(如果所有元素都包含您要编入索引的字段),则可以只提供列的字段名称 显然,人们也可以选择在内存中使用临时sqlite数据库。