如何将列表整数和字符串合并为一个字符串?

How to concat lists integers and strings into one string?

我有以下变量:

a = [1, 2, 3]
b = "de"  # <-- not a (usual) list !
c = 5     # <-- not a list !
d = [4, 5, 23, 11, 5]
e = ["dg", "kuku"]

现在我想将所有 a, b, c, d, e 连接到一个列表中:

[1, 2, 3, "de", 5, 4, 5, 23, 11, 5, "dg", "kuku"]

我试过 itertools.chain 但没用。请告知如何进行串联?

您必须合并 append()extend(),因为您的示例之一不是 listbc),而是一个整数.

#!/usr/bin/env python3
a = [1, 2, 3]
b = "de"
c = 5
d = [4, 5, 23, 11, 5]
e = ["dg", "kuku"]

the_input = [a, b, c, d, e]

result = []
for element in the_input:
    if isinstance(element, list):
        result.extend(element)
    else:
        result.append(element)

print(result)

我不知道有任何类似链的方法可以改进该示例。

chain 适用于可迭代对象。你的意思是:连接这些列表和原始值。

我看到两个步骤:

def ensure_list(x):
  if isinstance(x, list):
    return x
  return [x]

lists = map(ensure_list, (a, b, c, d, e))

concatenated = list(itertools.chain.from_iterable(lists))

您可以定义一个函数,它接受任意数量的参数并根据它们的类型迭代地构建一个列表,如下所示:

a = [1, 2, 3]
b = "de"  # <-- not a (usual) list !
c = 5     # <-- not a list !
d = [4, 5, 23, 11, 5]
e = ["dg", "kuku"]

def concat(*args):
    out = []
    for arg in args:
        if isinstance(arg, list):
            out.extend(arg)
        else:
            out.append(arg)
    return out

print(concat(a,b,c,d,e))

输出:

[1, 2, 3, 'de', 5, 4, 5, 23, 11, 5, 'dg', 'kuku']

或者,您可以映射 args 列表,确保它们都是列表,然后使用 itertools.chain 组合映射对象,如下所示:

def concat(*args):
    return list(itertools.chain(*map(lambda x : x if isinstance(x, list) else [x], args)))

print(concat(a,b,c,d,e))

输出:

[1, 2, 3, 'de', 5, 4, 5, 23, 11, 5, 'dg', 'kuku']

这里有一种更不透明的方式来完成同样的事情,只是为了在列表理解中获得乐趣:

def concat(*args):
    return [x
            for arg in args
            for x in (arg if isinstance(arg, list) else [arg])]


print(concat(a,b,c,d,e))

输出:

[1, 2, 3, 'de', 5, 4, 5, 23, 11, 5, 'dg', 'kuku']

您还可以创建一个带有 map 的生成器,它生成参数或列表中的参数,然后将它们与列表相加(您可能实际上不应该这样做,但它很简洁)。
def concat(*args):
    return sum(map(lambda arg : arg if isinstance(arg,list) else [arg], args), [])

print(concat(a,b,c,d,e))

输出:

[1, 2, 3, 'de', 5, 4, 5, 23, 11, 5, 'dg', 'kuku']

我不推荐这样做,但如果您喜欢列表理解或 one-liners:

,这里有另一种方法
to_concat = [a, b, c]
concatenated_list = []

concatenated_list += [item for sublist in [[list_or_val] if not isinstance(list_or_val, list) else list_or_val for list_or_val in to_concat] for item in sublist]

输出 a, b, c = "de", [1, 2], ["dg", "kuku"] :

In [6]: concatenated_list
Out[6]: ['de', 1, 2, 'dg', 'kuku']

它是如何工作的?

这部分:

[[list_or_val] if not isinstance(list_or_val, list) else list_or_val for list_or_val in to_concat]

的列表推导式通过将 non-list 值(如本例中的 a)转换为列表(因此 "de" 变为 ["de"])来创建一个新列表。我们称它为 list_of_lists。我们现在想要展平 list_of_lists 以获得我们的最终结果,我们可以通过列表推导的另一部分来实现:

[item for sublist in list_of_lists for item in sublist]

(有关扁平化的更多信息 here,如果您有兴趣)

如我所说,我不推荐此解决方案。理解起来相当混乱,而且它的性能可能很糟糕,因此它不适合更大的工作负载。

好问题 - 它导致制作一些我将放入我的实用程序工具箱的东西:

自定义生成器 - chainanything()

我会创建辅助函数作为生成器而不是返回列表。这使它的使用更加灵活,并且通常速度更快一点。如果我有一个 returns 列表的函数,我通常会这样做。

def chainanything(*args, preservestrings=True, recursive=False):
    """
    Generator: yields the contents of a Sequence, or the given object if not a Sequence, one at a time
    
    preservestrings = False will lead to strings being yielded as individual characters. Default = True
    recursive = True will recursively flatten sequences. Default = False
    
    Note: preservestrings = False, recursive = False will only flatten strings which are not part of another Sequence.
    e.g.: 'abc' -> 'a','b','c' but ['ab','cd'] -> 'ab','cd'
    """
    args = [*args]
    for arg in args:
        if not isinstance(arg, Sequence):
            yield arg
        else:
            if preservestrings and isinstance(arg, str):
                yield arg
            elif recursive:
                yield from flatten(arg)
            else:
                yield from arg

然后可以以标准形式使用它来提供您的预期结果:

def test_preservestring():
    # https://whosebug.com/questions/72288401/how-to-concat-lists-integers-and-strings-into-one-string/72288721#72288721
    a = [1, 2, 3]
    b = "de"  # <-- not a (usual) list !
    c = 5     # <-- not a list !
    d = [4, 5, 23, 11, 5]
    e = ["dg", "kuku"]
    assert [x for x in chainanything(a,b,c,d,e)] == [1, 2, 3, "de", 5, 4, 5, 23, 11, 5, "dg", "kuku"]

或用joinmap回答标题中的问题并将它们连接成一个字符串:

def test_join():
    a = [1, 2, 3]
    b = "de"  # <-- not a (usual) list !
    c = 5     # <-- not a list !
    d = [4, 5, 23, 11, 5]
    e = ["dg", "kuku"]
    assert ''.join(map(str,chainanything(a,b,c,d,e))) == "123de54523115dgkuku"

为了以合乎逻辑的方式处理字符串,整个函数比一行稍长。

展平函数递归展平序列 - 这是我为我的工具箱创建的另一个小助手生成器:

def flatten(seq):
    """
    Recursively flattens a sequence (including strings!) and returns all elements in order left to right.
    E.g.: [1,2,[3,4,[5],6],7,[8,9]] -> [1,2,3,4,5,6,7,8,9]
    """
    for item in seq:
        if not isinstance(item, Sequence):
            yield item
        elif len(item) == 1 and item[0] == item: #eg item = 'a'
            yield item[0]
        else:
            yield from flatten(item)

您可以在此处获取最新版本的助手:https://dev.azure.com/MusicalNinjas/_git/MikesMath