リストの要素が2つの空白の間にある場合にそれらを結合する


24

私はこのような入力をしています:

['assembly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c++']

次の''ような出力を得るために要素を結合したい:

['assembly', 'python', 'java', 'ruby', 'javascript', 'c++']

私は次のjoinようにスライスを使用してリストしようとしました:

a=['assembly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c++']
a[2:5] = [''.join(a[ 2: 5])]
a=['assembly', '', 'python', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c++']

これはある程度機能しますが、リスト全体に対してこの命令を反復する方法がわかりません。

回答:


27

使用itertools.groupby

from itertools import groupby

l = ['assembly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c++']
new_l = [''.join(g) for k, g in groupby(l, key = bool) if k]

出力:

['assembly', 'python', 'java', 'ruby', 'javascript', 'c++']

2
説明:これは「bool」を使用して、空の文字列やNoneなどの「Falsey」値をチェックします。
noɥʇʎԀʎzɐɹƆ

7

これはひどいとハックですが、

lambda b:lambda l:''.join(i or b for i in l).split(b)

リストの連結に含まれていないことを保証できる任意の文字列を取り、必要な機能を実行する関数を返すことができます。もちろん、特定の状況でこれを1回または2回だけ使用したい場合があるため、リストのどの要素にもスペースが含まれていないことが保証できる場合、次のようになります。

a = ['assembly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c++']
a = ''.join(i or ' ' for i in a).split(' ')

4

itertoolsを使用できない、または使用したくない場合:

l = ['assembly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c++']
l_new = []
combined = ""
for idx, s in enumerate(l):
    if s != "":
        combined += s
        if idx == len(l)-1:
            l_new.append(combined)

    else:
        l_new.append(combined)
        combined = ""

3

あなたはこれを行うことができます:

a = ['assembly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c++']
indx = ['' == k for k in a]
indx = [i for i, x in enumerate(indx) if x] # get the indices.
a_merged = a[0:indx[0]] + [''.join(a[indx[i]:indx[i+1]]) for i in range(len(indx)) if i < len(indx)-1] + a[indx[-1]+1:] # merge the list

出力:

['assembly', 'python', 'java', 'ruby', 'javascript', 'c++']

コメントの後に編集:

a = ['assembly', '','',  'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c++']
indx = [i for i, x in enumerate(a) if x == ''] # get the indices where '' occurs in the original list. 
a_merged = a[0:indx[0]] + [''.join(a[indx[i]:indx[i+1]]) for i in range(len(indx)) if i < len(indx)-1 and indx[i+1] -indx[i] > 1] + a[indx[-1]+1:]
a_merged

出力:

['assembly', 'python', 'java', 'ruby', 'javascript', 'c++']

# get the indices.あまり便利なコメントではありません。私はあなたがそれを有用にする(例えばfilter the indices to keep only those that correspond to whitespace)か、それを完全に削除することを提案します。
アレクサンダー-モニカを

また、その2ステップのプロセスを単純化して単純化できないのではないindices = [i for s in a if s == '']でしょうか。
アレクサンダー-モニカを復活

@Alexander 2行目の提案は構文エラーになると思います。3行目に「is equal to null string」チェックを追加するだけで2行目を削除できますindx = [i for i, x in enumerate(a) if x == '']
Reimus Klinsman

残念ながら、この回答は、最初または最後の要素が結合されるべきものであることを説明していません。以下のようなa = ['asse','mbly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c+', '+']それはあなたがの両端にヌル文字列でリストを追加することで、あなたのライン3を改善することができたように見えenumerate([''] + a + [''])、その後削除a[0:indx[0]]し、a[indx[-1]+1:]右隣お互いに2つのヌル文字列がある場合、あなたの線4にこれはまだを考慮していませんただし
Reimus Klinsman

1
良いコメントをありがとう@KeiNagase。編集を参照してください。
ナイーブ

2

入力区切り文字が実際には空の文字列である場合、次のことができます

strlist = [x or ' ' for x in a]
joined = ''.join(strlist).split()
joined
['assembly', 'python', 'java', 'ruby', 'javascript', 'c++']

関係のない文字列の答えは見つかりませんでした。パラメータなしでsplit()を実行すると、すべての空白が折りたたまれます。
realgeek

1

かなり古いですが、まだ便利です:

from itertools import groupby

lst = ['assembly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c++']

new_lst = [''.join(values)
           for key, values in groupby(lst, key = lambda x: x == '')
           if not key]
print(new_lst)

これは

['assembly', 'python', 'java', 'ruby', 'javascript', 'c++']

1

ループ
内のリストに対してループを実行し、要素を一時的な空の文字列に追加し、要素が空の文字列であるか、リストの最後の要素であるかを確認します。trueの場合、一時変数を出力リストに追加して値を変更しますその変数の空の文字列への
コード:

x=['assembly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c++']
temp=''
output=[]
for y in x:
    temp=temp+y
    if y=='' or y==x[-1]:
        output.append(temp)
        temp=''

print(output)

出力: ['assembly', 'python', 'java', 'ruby', 'javascript', 'c++']


1

私はCris回答がほとんどのpythonアプローチを使用することに同意しますが、Cris回答を少し適応させることは良いでしょう。を使用groupby(l,key = bool)して不要なあいまいさgroupby(l, key = lambda x: x !='')を取り除く代わりに

from itertools import groupby

separator = ''
l = ['assembly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c++']
new_l = [''.join(g) for k, g in groupby(l, key = lambda x: x !=separator) if k]

それがに記載されているとおりのPythonの禅明示的、暗黙よりも優れています

PS私はクリスの回答にコメントを書くのに十分な評判がないため、新しい回答を書いているだけです。


1

基本的なループ/テストのみを備えた別の作業バージョン:

txt = ['assembly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c++']

out = []
temp = ''

for s in txt:
   if s == '':
      if temp != '':
         out.append(temp) 
         temp = ''
      out.append('')
   else:
      temp = temp + s

if temp != '':
   out.append(temp)

out
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.