簡體   English   中英

查找列表中存在的給定長度的唯一子列表的最佳方法?

[英]Best way to find unique sublists of a given length that are present in a list?

因此,我構建了一個函數,用於查找給定列表中存在的所有長度為i的唯一子列表。

例如,如果您有list=[0,1,1,0,1]i=1 ,您只會得到[1,0] 如果i=2 ,你會得到[[0,1],[1,1],[1,0]] ,但不是[0,0]因為雖然它是10的可能組合,但它不存在在給定的列表中。 代碼如下所示。

雖然代碼起作用,但我不認為它是最有效的。 它依賴於查找所有可能的子列表並測試每個子列表的存在,這在i > 4 時變得不切實際(例如列表長度為 100)。 我希望我能得到幫助,找到一種更有效的計算方法。

我寫的代碼:

def present_sublists (l,of_length):
    """
    takes a given list of 1s and 0s and returns all the unique sublist of that
    string that are of a certain length
    """
    l_str=[str(int) for int in l]   #converts entries in input to strings
    l_joined="".join(l_str) #joins input into one strings, i.e. "101010"
    sublist_sets=set(list(itertools.combinations(l_joined,of_length)))
    #uses itertools to get all possible combintations of substrings, and then set
    #properties to removes duplicates
    pos_sublists=list(sublist_sets) #returns the set to a list
    sublists1=[]
    for entry in pos_sublists:         #returns the entries to a list
        sublists1.append(list(entry))
    for entry in sublists1:            #returns the "1"s and "0" to 1s and 0s
        for entry2 in entry:
            entry[entry.index(entry2)]=int(entry2)
    present_sublists=[]
    for entry in sublists1:            #tests whether the possible sublist is
                                       #present in the input list
        for x in range(len(l) - len(entry) + 1):
            if entry not in present_sublists:
                if l[x: x + len(entry)] == entry:
                    present_sublists.append(entry)
    output=present_sublists
    return output

給定您的代碼和示例,看起來您想要給定輸入的所有唯一連續子序列,如果是這樣,您不需要計算所有組合,也不需要在字符串、列表、集合和字符串之間移動,更不用說在事物上循環多次,使用切片表示法足以獲得期望的結果

>>> [0,1,2,3,4][0:2]
[0, 1]
>>> [0,1,2,3,4][1:3]
[1, 2]
>>> [0,1,2,3,4][2:4]
[2, 3]
>>> [0,1,2,3,4][3:5]
[3, 4]
>>> 

適當使用切片中的索引可以讓我們獲得任何給定大小的所有連續子序列(示例中為 2)

現在為了使這更加自動化,我們制作了一個適當的 for 循環

>>> seq=[0,1,2,3,4]
>>> size=2
>>> for i in range(len(seq)-size+1):
        print(seq[i:i+size])

    
[0, 1]
[1, 2]
[2, 3]
[3, 4]
>>> 

現在我們知道如何獲取我們關心的所有子序列,我們專注於只獲取唯一的子序列,因為我們當然使用集合但列表不能在集合中,所以我們需要一些可以,所以一個元組就是答案(它基本上是一個不可變的列表),這就是你需要的一切,讓我們把它們放在一起:

>>> def sub_sequences(seq,size):
        """return a set with all the unique contiguous sub-sequences of the given size of the given input"""
        seq = tuple(seq) #make it into a tuple so it can be used in a set
        if size>len(seq) or size<0: #base/trivial case
            return set() #or raise an exception like ValueError
        return {seq[i:i+size] for i in range(len(seq)-size+1)} #a set comprehension version of the previous mentioned loop

>>> sub_sequences([0,1,2,3,4],2)
{(0, 1), (1, 2), (2, 3), (3, 4)}
>>>
>>> #now lets use your sample
>>>
>>> sub_sequences([0,1,1,0,1],2)
{(0, 1), (1, 0), (1, 1)}
>>> sub_sequences([0,1,1,0,1],3)
{(1, 0, 1), (1, 1, 0), (0, 1, 1)}
>>> sub_sequences([0,1,1,0,1],4)
{(1, 1, 0, 1), (0, 1, 1, 0)}
>>> sub_sequences([0,1,1,0,1],5)
{(0, 1, 1, 0, 1)}
>>> 

讓我們標記位 0、1、2、3,......

讓我們還定義一個函數f(len, n) ,其中f(len, n)被定義為由出現在前n位中的所有長度為len的字符串組成。

所以

f(0, n) = {''}  since you can always make the empty string
f(len, 0) = set() if len > 0

那么如果len > 0 and n > 0f(len, n)的值是多少? 它包含f(len, n - 1)中的所有內容,加上 in 包含f(len - 1, n - 1)中的所有內容,並附加了l[n-1]

您現在擁有合理有效地找到f(of_length, len(l))所需的一切。

為了堅持你的功能足跡,我建議如下:

  1. 遍歷每個子列表並將它們放入 set() 以確保唯一性
  2. 子列表需要轉換為元組,因為列表不能被散列,因此不能按原樣放入集合中
  3. 將集合中的結果元組轉換回所需的格式。

在創建新列表時,列表推導是最有效和 Pythonic 的選擇方式。

>>> def present_sublists(l,of_length):
...   sublists = set([tuple(l[i:i+of_length]) for i in range(0,len(l)+1-of_length)])
...   return [list(sublist) for sublist in sublists]
...
>>> present_sublists([0,1,1,0,1], 1)
[[0], [1]]
>>> present_sublists([0,1,1,0,1], 2)
[[0, 1], [1, 0], [1, 1]]

暫無
暫無

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

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