12

Python 3でシーケンスを連結するための好ましい方法は何ですか?

今、私はやっています:

import functools
import operator

def concatenate(sequences):
    return functools.reduce(operator.add, sequences)

print(concatenate([['spam', 'eggs'], ['ham']]))
# ['spam', 'eggs', 'ham']

これを行うために2つの別々のモジュールをインポートする必要があるのは不格好なようです。

別の方法は次のとおりです。

def concatenate(sequences):
    concatenated_sequence = []
    for sequence in sequences:
        concatenated_sequence += sequence
    return concatenated_sequence

ただし、シーケンスがリストであることがわからないため、これは正しくありません。

あなたができること:

import copy

def concatenate(sequences):
    head, *tail = sequences
    concatenated_sequence = copy.copy(head)
    for sequence in sequences:
        concatenated_sequence += sequence
    return concatenated_sequence

しかし、それはひどくバグが発生しやすいようです-コピーを直接呼び出すのですか?head.copy()(リストとタプルで機能することは知っていますcopyが、シーケンスABCの一部ではないため、信頼できません...文字列が渡された場合はどうなりますか?)あなたが手渡された場合に備えて、突然変異を防ぐためにコピーする必要がありますMutableSequence。さらに、このソリューションでは、最初にシーケンスのセット全体を解凍する必要があります。再試行:

import copy 

def concatenate(sequences):
    iterable = iter(sequences)
    head = next(iterable)
    concatenated_sequence = copy.copy(head)
    for sequence in iterable:
        concatenated_sequence += sequence
    return concatenated_sequence

しかし、さあ...これはPythonです!だから...これを行うための好ましい方法は何ですか?

4

3 に答える 3

12

代わりに使用itertools.chain.from_iterable()します:

import itertools

def chained(sequences):
    return itertools.chain.from_iterable(sequences):

または、これをでタグ付けしたので、新しい構文を使用できyield fromます (インポートはありません!):

def chained(sequences):
    for seq in sequences:
        yield from seq

どちらも反復子を返します (完全なリストを具体化する必要list()がある場合は、それらを使用します)。ほとんどの場合、連結されたシーケンスからまったく新しいシーケンスを構築する必要はありません。実際には、それらをループして、代わりに何かを処理および/または検索したいだけです。

str.join()文字列の場合、私の回答または質問で説明されている手法の代わりに使用する必要があることに注意してください。

concatenated = ''.join(sequence_of_strings)

組み合わせて、シーケンスを迅速かつ正確に処理するには、次を使用します。

def chained(sequences):
    for seq in sequences:
        yield from seq

def concatenate(sequences):
    sequences = iter(sequences)
    first = next(sequences)
    if hasattr(first, 'join'):
        return first + ''.join(sequences)
    return first + type(first)(chained(sequences))

これは、タプル、リスト、および文字列に対して機能します。

>>> concatenate(['abcd', 'efgh', 'ijkl'])
'abcdefghijkl'
>>> concatenate([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> concatenate([(1, 2, 3), (4, 5, 6), (7, 8, 9)])
(1, 2, 3, 4, 5, 6, 7, 8, 9)

''.join()文字列のシーケンスにはより速い方を使用します。

于 2013-01-15T16:35:45.103 に答える
1

を使用しitertools.chain.from_iterableます。

import itertools

def concatenate(sequences):
    return list(itertools.chain.from_iterable(sequences))

への呼び出しlistは、実際の新しいリストが必要な場合にのみ必要なので、この新しいシーケンスを 1 回繰り返すだけの場合はスキップしてください。

于 2013-01-15T16:34:40.013 に答える