簡體   English   中英

是否有更多Pythonic方式有條件地合並相鄰的列表元素?

[英]Is there a more Pythonic way to conditionally merge adjacent list elements?

假設我有以下列表。

myList = ["echo FooBar \\", "and some more foos", "cat /etc/cpuinfo", 
    "cat /path/to/\\", "long/deep/directory/\\", "that/goes/on/forever"]

我想合並任何以\\結尾的元素與右邊的元素,刪除過程中的\\ ,並繼續這樣做,直到沒有更多元素帶尾隨\\

正確的輸出看起來像這樣。

['echo FooBar and some more foos', 
 'cat /etc/cpuinfo', 
 'cat /path/to/long/deep/directory/that/goes/on/forever']

這是我目前的解決方案,它是功能性的,但似乎比必要的復雜得多。

myList = ["echo FooBar \\", "and some more foos", "cat /etc/cpuinfo", 
    "cat /path/to/\\", "long/deep/directory/\\", "that/goes/on/forever"]

tmpItem = None
tmpList = []

for x in myList:
   if tmpItem:
     if tmpItem.endswith("\\"):
        tmpItem = tmpItem[:-1] + x
     else:
        tmpList.append(tmpItem)
        tmpItem = x
   else: tmpItem = x

if tmpItem:
     if tmpItem.endswith("\\"):
        tmpList.append(tmpItem[:-1])
     else:
        tmpList.append(tmpItem)

print tmpList

有沒有更簡潔的方法在Python中執行此操作,可能使用更實用的習慣用法?

我看了一下reduce() ,但它似乎只讓你將一個減少從一個列表移動到一個元素,而不是另一個列表,但也許我低估了它的力量。

不確定是否更加pythonic,但肯定更簡潔。

"\0".join(myList).replace("\\\0","").split("\0")

如果您不能假設字符串不包含\\0 ,則可以生成分隔符:

import string
import random
sep = ""
while any(sep in s for s in myList):
    sep += random.choice(string.ascii_uppercase + string.digits)
sep.join(myList).replace("\\"+sep,"").split(sep)
myList = ["echo FooBar \\", "and some more foos", "cat /etc/cpuinfo", 
    "cat /path/to/\\", "long/deep/directory/\\", "that/goes/on/forever"]
ret = []
for i in myList:
    if ret and ret[-1].endswith('\\'):
        ret[-1] = ret[-1][:-1] + i
    else:
        ret.append(i)

print ret

版畫

['echo FooBar and some more foos', 'cat /etc/cpuinfo',
 'cat /path/to/long/deep/directory/that/goes/on/forever']

如果這對你來說是pythonic:

reduce(lambda agg, x: (agg +
                        [agg.pop()[:-1] + x] if agg[-1].endswith('\\') else
                         agg + [x]) if len(agg) > 0 else
                         agg + [x], myList, [])

我覺得理解它很酷很有用(即使不使用)

說明:使用reduce的聚合列表,並在需要時回溯到要附加到的最后一個元素。 否則附加到列表。 不回頭看第一個元素以避免異常。

['echo FooBar和一些更多的foos','cat / etc / cpuinfo','cat / path / to / long / deep / directory / that / go / on / forever']

一個可能更容易閱讀的解決方案是

wp = 0
for L in myList:
    if wp and myList[wp - 1].endswith('\\'):
        myList[wp - 1] = myList[wp - 1][:-1] + L
    else:
        myList[wp] = L
        wp += 1
del myList[wp:]

對我來說這更容易閱讀,因為用於修改數組的wp “寫指針”模式是我手指上的東西。 可讀性在旁觀者的眼中......

一個純功能的解決方案(根本沒有任務)可能

def merge_continuations(L, ix=0):
    if ix >= len(L)-1:
        return L
    elif L[ix].endswith('\\'):
        return merge_continuations(L[:ix] +
                                   [L[ix][:-1] + L[ix+1]] +
                                   L[ix+2:], ix)
    else:
        return merge_continuations(L, ix+1)

但它確實不屬於Python。

另一個版本可以寫成生成器,接受任何可迭代:

def merge_continuations(it):
    prefix = None
    for L in it:
        if prefix is None:
            prefix = L
        elif prefix.endswith('\\'):
            prefix = prefix[:-1] + L
        else:
            yield prefix
            prefix = L
    if prefix is not None:
        yield prefix

不是我喜歡的方法,而是Python中的慣用法

它可能不是最短的,但它相當可讀和Pythonic。

out, grp = [], []
for s in my_list:
    if s.endswith('\\'):
        grp.append(s[:-1])
    else:
        out.append(''.join(grp) + s)
        grp = []

print(out)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM