如何在 3D 列表中返回重复?



我有一个疯狂的 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]]]

给定:

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]]]

这是一个简单的解决方案:

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()

如果您在调用函数时遇到困难,则代码包含文档字符串。main()方法显示了如何使用它。不要忘记指定depth否则您会在整个列表中获得最常见的数字。例如,给定,它将是1.如果要在两个或多个元素共享最常见的属性时返回不同的值,请创建新的decider函数并将其传递到most_common_nested函数中。

最新更新