問題描述
將列表列表減少為字典,以子列表大小為鍵,出現次數為值 (Reduce list of list to dictionary with sublist size as keys and number of occurances as value)
我有一個列表列表,我想計算具有特定大小的子列表出現的次數。
例如。對於列表 [[1], [1,2], [1,2], [1,2,3]]
我希望得到 {1: 1, 2: 2, 3: 1}
我試過 reduce
函數,但 += 1
有語法錯誤,不知道是什麼錯了。
list_of_list = [[1], [1,2], [1,2], [1,2,3]]
result = functools.reduce(lambda dict,list: dict[len(list)] += 1, list_of_list, defaultdict(lambda: 0, {}))
## 參考解法 #### 方法 1:
It is not a good idea to use reduce
in such a complicated way when you can use collections.Counter()
with map()
function in a more Pythonic way:
>>> A = [[1], [1,2], [1,2], [1,2,3]]
>>> from collections import Counter
>>>
>>> Counter(map(len,A))
Counter({2: 2, 1: 1, 3: 1})
Note that using map
will perform slightly better than a generator expression because by passing a generator expression to Counter()
python will get the values from generator function by itself, since using built‑in function map
has more performance in terms of execution time1.
~$ python ‑m timeit ‑‑setup "A = [[1], [1,2], [1,2], [1,2,3]];from collections import Counter" "Counter(map(len,A))"
100000 loops, best of 3: 4.7 usec per loop
~$ python ‑m timeit ‑‑setup "A = [[1], [1,2], [1,2], [1,2,3]];from collections import Counter" "Counter(len(x) for x in A)"
100000 loops, best of 3: 4.73 usec per loop
From PEP 0289 ‑‑ Generator Expressions:
The semantics of a generator expression are equivalent to creating an anonymous generator function and calling it. For example:
g = (x**2 for x in range(10)) print g.next()
is equivalent to:
def __gen(exp): for x in exp: yield x**2 g = __gen(iter(range(10))) print g.next()
Note that since generator expressions are better in terms of memory use, if you are dealing with large data you'd better use generator expression instead of map function.
方法 2:
You can do this using Counter as well:
list_of_list = [[1], [1,2], [1,2], [1,2,3]]
c = Counter(len(i) for i in list_of_list)
Output:
Counter({2: 2, 1: 1, 3: 1})
方法 3:
reduce
is an inferior tool for this job.
Look at a collections.Counter
instead. It's a dict subclass, so you should be able to use it however you were planning to use the dict.
>>> from collections import Counter
>>> L = [[1], [1, 2], [1, 2], [1, 2, 3]]
>>> Counter(len(x) for x in L)
Counter({1: 1, 2: 2, 3: 1})
(by WojciechKo、Mazdak、idjaw、wim)