【问题标题】:Optimize algorithm to work with tuples, sets and dictionarys优化算法以处理元组、集合和字典
【发布时间】:2019-10-01 11:20:16
【问题描述】:

我有一个列表展平算法:

def flatten(s):
    if not s:
        return s
    if isinstance(s[0], (list, set, tuple)):
        return flatten(s[0]) + flatten(s[1:])
    return s[:1] + flatten(s[1:])

但如果您将两种不同数据类型结合起来,它就不起作用了。例如,元组内的列表。有没有办法做到这一点?也可以扁平化字典吗?值,而不是键。

【问题讨论】:

标签: python algorithm flatten


【解决方案1】:

通常建议使用 itertools -> 链或标准库,但对于任意嵌套的容器:

xlen = len(x)
result = []    

def flatten(x, i, xlen, result):
  if i >= xlen:
    return
  if not isinstance(x[i], (list, set, tuple)):
    result.append(x[i])
  else:
    flatten(list(x[i]), 0, len(x[i]), result)
  flatten(x, i+1, xlen, result)

您可以为空容器等添加角盒。

【讨论】:

  • 对于任意深度展平,请告诉我如何使用itertools.chain 摆脱递归。
  • 更新了答案,但你知道我可以混合使用链和递归来赢得争论:)
【解决方案2】:

在 SO 上有几种算法可以展平嵌套列表和元组,但我们会坚持使用您的算法。第一个观察结果是您编写的算法不适用于set 实例,因为它们不可下标。所以套装必须走:

def flatten(s):
    if not s:
        return s
    if isinstance(s[0], (list, tuple)):
        return list(flatten(s[0])) + list(flatten(s[1:]))
    return list(s[:1]) + list(flatten(s[1:]))

flatten([[1,2,(3,4,(5,6))]])

打印:

[1, 2, 3, 4, 5, 6]

【讨论】:

  • 谢谢,这真的很有帮助。这里的所有答案都有效!
【解决方案3】:

如果您正在寻找优化和一些乐趣... 递归没问题,但不要忘记 RecursionError。

输入:

from datetime import datetime
from typing import Sequence


def timer(f):
    def wrapped(s):
        start = datetime.now()
        result = f(s)
        print(datetime.now() - start)
        return result
    return wrapped


@timer
def str_method(s: Sequence):
    return [int(x) for x in
            str(s).replace("(", "[").replace(")", "]")[1:-1].replace("[", "").replace("]", "")
            if x not in [",", " "]]


def flatten(s: Sequence):
    if not s:
        return s
    if isinstance(s[0], (list, tuple)):
        return list(flatten(s[0])) + list(flatten(s[1:]))
    return list(s[:1]) + list(flatten(s[1:]))

if __name__ == '__main__':
    s = [1, 2, (3, 4, (5, 6))]
    start = datetime.now()
    print(flatten(s))
    print(datetime.now() - start)
    print(str_method(s))
    print("-")
    s = [(x, ) for x in range(100)]
    start = datetime.now()
    flatten(s)
    print(datetime.now() - start)
    str_method(s)
    print("-")
    s = [(x, ) for x in range(100000)]
    start = datetime.now()
    try:
        print(flatten(s))
    except RecursionError:
        print("RecursionError")
    str_method(s)

输出:

[1, 2, 3, 4, 5, 6]
0:00:00.000022 # flatten
0:00:00.000041 # str_method
[1, 2, 3, 4, 5, 6]
-
0:00:00.000369 # flatten
0:00:00.000122 # str_method
-
RecursionError # flatten
0:00:00.186894 # str_method

【讨论】:

    【解决方案4】:

    其他答案都是有效的,但是如果您将sympy 导入到您的代码中,也许使用它的 flatten 方法?速度非常快,可以满足您的需求。

    【讨论】:

    • 我选择这个答案只是因为我实际上碰巧使用了 sympy!机会有多大?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-20
    • 1970-01-01
    • 2013-07-17
    • 2014-07-02
    • 2018-10-04
    相关资源
    最近更新 更多