我有一个列表列表,其中元素0中的项目与元素1中的值相关联。每个项目可能出现多次。我想创建一个唯一项目列表,其中每个项目的最大值都与之相关。我的代码实现了这一点,但似乎非常低效。此外,这是一个简化的例子。 mylist
可能是100,000行。有关提高效率的建议吗?
mylist = [['Item 1', 12],['Item 1', 10], ['Item 3', 12],['Item 4', 10], ['Item 3', 14]]
# get unique items
my_unique_items = list(set(x[0] for x in mylist))
# make it a list of list
my_unique_items = [[x] for x in my_unique_items]
# iterate over list items
for item in my_unique_items:
# do list comp to get max value and append
item.append(max([x[1] for x in mylist if x[0] == item[0]]))
print my_unique_items
答案 0 :(得分:1)
仅循环mylist
一次会更有效率。如果您只关心每个项目键的最大值,只需保留项目及其最大值的映射,并在列表中进行比较。
这是最糟糕的O(n)情况,而你的原始情况最糟糕的是O(n ^ 2)。
item_maxes = {}
for item in mylist:
max_value = item_maxes.setdefault(item[0], None)
if max_value is None or item[1] > max_value:
item_maxes[item[0]] = item[1]
编辑:我认为此方法的ShadowRanger's版本看起来更清晰:
max_vals = {} for item, value in mylist: max_vals[item] = max(max_vals.get(item, value), value)
答案 1 :(得分:1)
如果输入已经排序(或者您希望输出排序),那么使用itertools.groupby
的方法很好:
from future_builtins import map # On Python 2.x only, to get generator based map
from itertools import groupby
from operator import itemgetter
# Nicer names, and avoid recreating getvalue on each loop
getitem, getvalue = itemgetter(0), itemgetter(1)
# If not already sorted, must sort by same key we're grouping on:
mylist.sort(key=getitem)
max_vals = [(k, max(map(getvalue, g))) for k, g in groupby(mylist, key=getitem)]
如果您不关心订单,并且您的商品是可清洗的,dict
通常会更快(如果大多数items
是唯一的,则可能会使用更多的内存):
max_vals = {}
for item, value in mylist:
max_vals[item] = max(max_vals.get(item, value), value)
答案 2 :(得分:0)
使用itertools
模块中的groupby
和operator
模块中的itemgetter
。
>>> from itertools import groupby
>>> from operator import itemgetter
>>> d = {}
>>> for g, data in groupby(sorted(mylist, key=itemgetter(0)), key=itemgetter(0)):
... d[g] = max(list(zip(*data))[1])
...
>>> d
{'Item 1': 12, 'Item 3': 14, 'Item 4': 10}
您也可以使用itertools.islice
,而不是使用list
构造函数和普通切片操作。
>>> for g, data in groupby(sorted(mylist, key=itemgetter(0)), key=itemgetter(0)):
... d[g] = max(*islice(zip(*data), 1, None))
...
>>> d
{'Item 1': 12, 'Item 3': 14, 'Item 4': 10}