我有一个疯狂的3D列表,我想返回所有重复或频繁出现在我的3D列表,但我不知道该写什么代码。
例如下面是我的3D列表
df = [[[10,16,25],[5,12,15],[7,12,25]],[[5,10,17],[15,20],[21,25,30],[10,17]],[[2,7],[4,8,10]],[[16,17,21],[17,32,41],[17,20],[22,24,41]]]
我希望我的结果是这样的
df1 = [[[12],[25]],[[10],[17],[[ ]],[[17],[41]]]
这里有一个简单的解决方案。
from collections import Counter
result=[]
for l in df:
c_outter=Counter()
for sl in l:
c_outter+=Counter(sl)
result.append([[e] for e in c_outter if c_outter[e]>1])
>>> result
[[[25], [12]], [[10], [17]], [], [[17], [41]]]
哪一个... 可以 被简化为更复杂的理解。
>>> [[[k] for k,v in sum((Counter(sl) for sl in l),Counter()).items() if v>1]for l in df]
[[[25], [12]], [[10], [17]], [], [[17], [41]]]
寻找列表中最常见元素的代码可以找到 此处. 但是,如果你在像你这样的嵌套列表中搜索它,这并不能帮助你,所以我创建了一个程序来演示一个可能的解决方案。它也包含了你的例子列表,所以你可以看到结果。根据你的意愿修改它。
from collections import Counter
from collections.abc import Iterable
import json
def most_common(coll, decider=lambda x: None):
"""
Returns the most common element in a collection.
If two or more elements are the most common ones,
uses passed decider function to decide what to return.
None is returned if collection is empty or cannot be iterated.
Args:
coll (iterable): Collection of elements.
decider (function(list of tuples (element, frequency)), default: return None):
Decides stalemates.
Returns:
Element type of coll: success
NoneType: coll has no elements or could not be iterated
"""
# check if coll can be searched for most common elements
if len(coll) == 0 or not isinstance(coll, Iterable):
return None
# get elements sorted by their frequency in descending order
elements_frequency = Counter(coll).most_common()
# get the most common elements (highest and same frequency)
most_common_elements = [
item for item in elements_frequency if item[1] == elements_frequency[0][1]
]
# if only single most common item exists, return it
if len(most_common_elements) == 1:
return most_common_elements[0][0]
# else use decider function
return decider(most_common_elements)
def decider_min(elements_frequency):
"""
Returns the smallest element. Does not look towards the frequency.
Args:
elements_frequency (list of tuples (element, frequency))
"""
return min([item[0] for item in elements_frequency])
def flat_nested(coll):
"""
Returns single depth iterable.
For example:
flat_nested( [ [1, 2, 3], [1, 2] ])
Output:
[1, 2, 3, 1, 2]
Args:
coll (iterable): Collection of elements with consistent depth distribution.
This means collections like this:
[ [1, 2], 2 ]
Will not work.
Returns:
Iterable
"""
if not isinstance(coll, Iterable):
return None
current_level = []
for item in coll:
next_level = flat_nested(item)
if next_level is None:
break
current_level.extend(next_level)
else:
return current_level
return coll
class NotIterable:
# simple class for noting that the function reached final depth
def __init__(self):
pass
def recursive_mcn_helper(coll, current_depth, target_depth, decider):
"""
Recursive helper function for most_common_nested function.
Should not be called on its own.
Args:
coll (iterable)
current_depth (int)
target_depth (int):
Depth level at which the collection is flattened
and most common element from that depth is returned.
decider (function(list of tuples (element, frequency)), default: return None):
Decider function for multiple most common elements.
Returns:
NoneType - most_common defaults
NotIterable - final depth reached, compute most_common from previous level
Iterable - this depth contained only iterables
Element type - computed most_common value
"""
if not isinstance(coll, Iterable):
return NotIterable()
if current_depth == target_depth:
return most_common(flat_nested(coll), decider)
current_level = []
for item in coll:
next_level = recursive_mcn_helper(item, current_depth + 1, target_depth, decider)
if isinstance(next_level, NotIterable):
break
current_level.append(next_level)
else:
return current_level
return most_common(coll, decider)
def most_common_nested(coll, target_depth=0, decider=lambda x: None):
"""
Returns list of most common elements computed from elements
at final depths and target_depth.
Args:
coll (iterable)
target_depth (int):
Depth level at which the collection is flattened
and most common element from that depth is returned.
decider (function(list of tuples (element, frequency)), default: return None):
Decider function for multiple most common elements.
Returns:
NoneType: coll is not an Iterable
List: success
"""
if not isinstance(coll, Iterable):
return None
return [recursive_mcn_helper(coll, 0, target_depth, decider)]
list_3d = [
[
[10, 16, 25],
[5, 12, 15],
[7, 12, 25]
],
[
[5, 10, 17],
[15, 20],
[21, 25, 30],
[10, 17]
],
[
[2, 7],
[4, 8, 10]
],
[
[16, 17, 21],
[17, 32, 41],
[17, 20],
[22, 24, 31]
]
]
def main():
# called at the start of the program
# depth 0
mcn_coll_0 = most_common_nested(list_3d, 0, decider_min)
# depth 1
mcn_coll_1 = most_common_nested(list_3d, 1, decider_min)
# depth 2
mcn_coll_2 = most_common_nested(list_3d, 2, decider_min)
# print the collections with nice indentation
print(f"""Most common at depth 0 (whole collection flattened):
{json.dumps(mcn_coll_0, indent=4)}
Most common at depth 1 (first sub lists):
{json.dumps(mcn_coll_1, indent=4)}
Most common at final depth (last sub lists):
{json.dumps(mcn_coll_2, indent=4)})""")
main()
如果你在调用函数时有困难,代码中包含了docstrings. main()
方法展示了如何使用它。不要忘记指定 depth
否则你会得到整个列表中最常见的数字。例如,给定的例子,它将是 1
. 如果你想在两个或两个以上的元素共享最常见的属性时返回不同的值,请创建新的 decider
函数,并将其传入 most_common_nested
职能。