Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/amazon-web-services/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python实现可变串联运算符_Python_Performance_Recursion_Optimization_Concatenation - Fatal编程技术网

Python实现可变串联运算符

Python实现可变串联运算符,python,performance,recursion,optimization,concatenation,Python,Performance,Recursion,Optimization,Concatenation,澄清: 我刚刚意识到我下面的定义和代码可能是错误的,因为它们没有考虑嵌套列表。我真的希望,concatenate的最终结果要么是一个不是列表的对象,要么是一个多个不是列表的对象的列表(因此没有嵌套列表)。空列表应该变成空对象 但是用户可以提供由嵌套列表组成的输入,在这种情况下,我需要对它们进行删除。抱歉,我没有说清楚 我有某种类型的对象(也可以将空作为值),我在这些对象上有一个满足以下公理的二进制连接运算符(这里[a,B]表示包含a和B的列表): concatenate2(空,A)=conca

澄清:

我刚刚意识到我下面的定义和代码可能是错误的,因为它们没有考虑嵌套列表。我真的希望,
concatenate
的最终结果要么是一个不是列表的对象,要么是一个多个不是列表的对象的列表(因此没有嵌套列表)。空列表应该变成空对象


但是用户可以提供由嵌套列表组成的输入,在这种情况下,我需要对它们进行删除。抱歉,我没有说清楚

我有某种类型的对象(也可以将空作为值),我在这些对象上有一个满足以下公理的二进制连接运算符(这里[a,B]表示包含a和B的列表):

concatenate2(空,A)=concatenate2(A,空)=A
连接2(A[B,C])=连接2([A,B],C)=[A,B,C]
串联2(A,B)=[A,B](如果A,B与前面的任何情况不匹配)。
现在我还想得到任意多个术语的串联:

我希望以最小化列表复制操作数量的方式实现这些操作符,但我不确定如何在Python中做到最好

我现在的想法是这样做:

这看起来很好,很清晰,但我不知道它在性能和内存使用方面有多好。我担心在每次[…]+[…]操作期间可能会导致太多列表副本

有没有更好的方法来实施这些操作


请注意,实际上只需要执行
串联操作。
concatenate2
运算符用于给出一个很好的递归定义,但是如果有人能够提出一个更有效的解决方案,而不使用它,我也会接受。

使用
+
进行重复连接并不理想,因为它会不断为每个二进制连接创建中间
列表
对象,从而导致组合长度的二次最坏情况时间复杂度。一种更简单、更好的方法是具有线性复杂性的嵌套理解。 这还使用
*
运算符来解包任意数量的参数:

def concatenate(*terms):
    return [x for t in terms for x in (t if isinstance(t, list) else [t])]

>>> concatenate([3, 4], 5, [], 7, [1])
[3, 4, 5, 7, 1]

>>> concatenate()
[]

使用
+
进行重复连接并不理想,因为它会不断为每个二进制连接创建中间
列表
对象,从而导致组合长度的二次最坏情况时间复杂度。一种更简单、更好的方法是具有线性复杂性的嵌套理解。 这还使用
*
运算符来解包任意数量的参数:

def concatenate(*terms):
    return [x for t in terms for x in (t if isinstance(t, list) else [t])]

>>> concatenate([3, 4], 5, [], 7, [1])
[3, 4, 5, 7, 1]

>>> concatenate()
[]

您似乎想要的不仅仅是可变的,还有混合类型的签名

假设我们想定义一个
concatenate_all(*args)
函数来连接抛出的所有参数

如果您同意
concatenate\u all
的所有参数都是序列,那么我们可以将它们组成一个序列,并用
concatenate
左折:

import itertools

# Pretend that concatenate_all is [[A]] -> [A]
def concatenate_all(*seqs):
  all_seqs = itertools.chain(*seqs)
  return reduce(lambda acc, x: concatenate(acc, x), all_seqs, EMPTY)
如果我们假设一些
arg
是标量,一些是列表,那么我们可以将标量包装到列表中并使用相同的技巧

def concatenate_all(*scalars_or_seqs):
  def to_list(x):
      # TODO: should make it work with generators, too.
      return x if isinstance(x, list) else [x]

  # We use itertools to avoid creating intermediate lists.
  all_items = itertools.chain(*scalars_or_seqs)
  all_lists = itertools.imap(to_list, all_items)
  return reduce(lambda acc, x: concatenate(acc, x), all_lists, EMPTY)
如果我们假设一些
arg
也是需要展平的嵌套列表,那么您可以更新上面的代码来处理这个问题


我想警告您,不要让函数在参数方面过于聪明。最初可能会有过多的魔力,但在实践中变得很难推理,特别是在使用Python这样的高度动态语言时,几乎没有静态检查。最好将换行和展平推到调用方,并使其显式化。

您似乎想要的不仅仅是可变的,还有混合类型的签名

假设我们想定义一个
concatenate_all(*args)
函数来连接抛出的所有参数

如果您同意
concatenate\u all
的所有参数都是序列,那么我们可以将它们组成一个序列,并用
concatenate
左折:

import itertools

# Pretend that concatenate_all is [[A]] -> [A]
def concatenate_all(*seqs):
  all_seqs = itertools.chain(*seqs)
  return reduce(lambda acc, x: concatenate(acc, x), all_seqs, EMPTY)
如果我们假设一些
arg
是标量,一些是列表,那么我们可以将标量包装到列表中并使用相同的技巧

def concatenate_all(*scalars_or_seqs):
  def to_list(x):
      # TODO: should make it work with generators, too.
      return x if isinstance(x, list) else [x]

  # We use itertools to avoid creating intermediate lists.
  all_items = itertools.chain(*scalars_or_seqs)
  all_lists = itertools.imap(to_list, all_items)
  return reduce(lambda acc, x: concatenate(acc, x), all_lists, EMPTY)
如果我们假设一些
arg
也是需要展平的嵌套列表,那么您可以更新上面的代码来处理这个问题


我想警告您,不要让函数在参数方面过于聪明。最初可能会有过多的魔力,但在实践中变得很难推理,特别是在使用Python这样的高度动态语言时,几乎没有静态检查。最好将换行和展平推到调用方并使其显式化。

应该如何
concatenate2([A,B],[C,D])
?(这种设计似乎在某种程度上混淆了类型,这只会让人头疼。)它应该返回[a,B,C,D](假设这些都不是列表)。所以你也要展平嵌套列表吗?是的,我刚刚意识到我上面的定义可能是错误的,因为它没有考虑嵌套列表。我真的希望,
concatenate
的最终结果是一个不是列表的对象,或者一个这样的对象列表(因此没有嵌套列表)。concatenate2([a,B],[C,D])
应该怎么做?(这种设计似乎在某种程度上混淆了类型,这只会让人头疼。)它应该返回[a,B,C,D](假设这些都不是列表)。所以你也要展平嵌套列表吗?是的,我刚刚意识到我上面的定义可能是错误的,因为它没有考虑嵌套列表。我真的希望,
concatenate
的最终结果是一个不是列表的对象,或者一个这样的对象的列表(因此没有嵌套列表)。只是为了确定,isinstance(t,list)是否与type(t)==list相同?它更自由一些,因为它也将