【问题标题】:How do you return repeats in a 3d list?如何在 3d 列表中返回重复?
【发布时间】:2020-09-02 08:59:02
【问题描述】:

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

【问题讨论】:

  • 您对哪个部分有问题?欢迎来到 SO。这不是讨论论坛或教程。请使用tour 并花时间阅读minimal reproducible exampleHow to Ask 以及该页面上的其他链接。
  • 我不知道要写什么代码。
  • 花点时间和the Tutorial一起练习例子。它会让你了解 Python 提供的工具来帮助你解决问题。
  • 您能指出哪些子阵列产生您想要的输出吗?
  • 我阅读了教程,但它并没有真正回答我正在寻找的内容。还有其他方法吗

标签: python python-3.x list multidimensional-array jupyter-notebook


【解决方案1】:

查找列表中最常见元素的代码可以在here 找到。但是,如果您在像您这样的嵌套列表中搜索它,这对您没有帮助,因此我创建了一个程序来演示可能的解决方案。它还包含您的示例列表,因此您可以看到结果。随意修改:

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 函数。

【讨论】:

  • 感谢您的帮助。我已经编辑了我的问题和结果。希望它会得到更好的理解。基本上想返回重复而不是最常见的。我希望我的结果是这样的 df1 = [[[12],[25]],[[17],[[ ]],[[17],[31]]]
【解决方案2】:

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

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

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-10-04
  • 1970-01-01
  • 2018-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-01
相关资源
最近更新 更多