簡體   English   中英

連接並簡化包含數字和字母對的列表

[英]Concatenate and simplify a list containing number and letter pairs

我有一個代表數字的字符串列表。 我不能使用 int,因為有些數字帶有附加字母,例如“33a”或“33b”

['21', '23a', '23b', '23k', '23l', '23x', '25', '33a', '33b', '33c', '33d', '33e', '33f', '34', '34', '35a', '35a' ]

我的目標是將數字連接成一個字符串並使用正斜杠將它們分開。

如果一個數字重復並且其附加字母按字母順序繼續,則表示應簡化如下:

['23a'/'23b'] --> '23a-b'

如果一個數字在沒有附加字母的情況下重復出現,它應該只列出一次。 這同樣適用於重復相同的數字對和附加字母。

對於完整示例,所需的 output 如下所示:

'21/23a-b/23k-l/23x/25/33a-f/34/35a'

使用以下代碼,我能夠連接數字並排除重復項,但我未能根據上述示例嘗試用字母簡化數字。

numbers = ['21', '23a', '23b', '23k', '23l', '23x', '25', '33a', '33b', '33c', '33d', '33e', '33f', '34', '34', '35a', '35a' ]

concat_numbers = ""
numbers_set = list(set(numbers))

numbers_set.sort()
for number in numbers_set: 
    concat_numbers += number + "/"
    
print(concat_numbers)
>>> '21/23a/23b/23k/23l/23x/25/33a/33b/33c/33d/33e/33f/34/35a/'

關於如何以最 pythonic 方式實現這一點的任何提示?

這可以通過利用 defaultdict(list) 並重新創建您的 output 來完成,如下所示:

data = ['21', '23a', '23b', '23k', '23l', '23x', '25', '33a', '33b', 
        '33c', '33d', '33e', '33f', '34', '34', '35a', '35a']
data.sort() # easier if letters are sorted - so sort it

from collections import defaultdict
from itertools import takewhile
d = defaultdict(list)
for n in data:
    # split in number/letters
    number = ''.join(takewhile(str.isdigit, n))
    letter = n[len(number):]
    # add to dict
    d[number].append(letter)

print(d)

我們現在有一個以“數字”作為鍵,所有字母作為列表的字典,需要進一步清理它:

# concat letters that follow each other
def unify(l):
    u = [""]
    # remember start/end values
    first = l[0]
    last = l[0]
    # iterate the list of letters given
    for letter in l:
        # for same letters or a->b letters, move last forward
        if last == letter or ord(last) == ord(letter)-1:
            last = letter
        else:
            # letter range stopped, add to list
            u.append(f"{first}-{last}")
            # start over with new values
            first = letter
            last = letter
    # add if not part of the resulting list already
    if  not u[-1].startswith(first):
        # either single letter or range, then add as range
        u.append( first if last == first else f"{first}-{last}")

    # ignore empty results in u
    return ",".join( (w for w in u if w) )

# unify letters
for key,value in d.items():
    d[key] = unify(value)

print(d)

然后構建最終的 output:

r = "/".join(f"{ky}{v}" for ky,vl in d.items() for v in vl.split(","))
print(r)

Output:

# collected splitted key/values
defaultdict(<class 'list'>, 
{'21': [''], '23': ['a', 'b', 'k', 'l', 'x'], 
 '25': [''], '33': ['a', 'b', 'c', 'd', 'e', 'f'], 
 '34': ['', ''], '35': ['a', 'a']})

# unified values
defaultdict(<class 'list'>, 
{'21': '', '23': 'a-b,k-l,x', '25': '', 
 '33': 'a-f', '34': '', '35': 'a'})

# as string
21/23a-b/23k-l/23x/25/33a-f/34/35a       

暫無
暫無

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

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