簡體   English   中英

將列表與保留順序中元素的其他列表進行比較

[英]Compare lists with other lists for elements in preserved order

我有一些單詞列表。 一些列表彼此共享共同的單詞。 我正在嘗試查看每個列表,其他列表具有相同序列中的常用詞。 例如,假設這些是我的列表(為簡單起見,使用字母而不是單詞/字符串):

list1 = [a,b,c,d]
list2 = [f,n,a,b,g]
list3 = [x,f,g,z]
list4 = [y,a,b,f,g,k]

在這里,我們可以看到list1中的[a,b]也在list2和list4中以該順序出現。 我們還可以看到list3中的[f,g]出現在list4中。 因此,我們將這些列表相互映射如下:

list1: list2, list4 #(contains [a,b])
list2: list1, list4 #(contains [a,b])
list3: list4 #(contains [f,g])
list4: list1, list2, list3 #(contains [a,b] and [f,g])

您可以忽略這些注釋,因為這是為了解釋,它只是彼此映射的列表名稱。 請注意,即使list2具有元素'f'和'g',因為它們不是[f,g]的順序,它不會映射到list3或list4。

我已經使用set.intersection()編寫了一個函數來獲取所有列表中的常用單詞,但它並不關心順序。 所以,我似乎無法弄清楚要使用哪種數據結構或算法,以便以這種方式將列表相互映射。

我正在嘗試以下方法,其中單詞列表是我的列表列表,每個列表包含各自的單詞數量:

filelist = {}
for i in range(0, len(wordlists)):
    current_wordlist = wordlists[i]
    for j, j_word in enumerate(current_wordlist):
        if current_wordlist[j] == j_word:
            if j_word not in filelist:
                filelist[i] = {j}
            else:
                filelist[i].append(j)

但它沒有正確映射,因為它沒有映射到正確的列表號。 我會很感激一些反饋或其他一些檢查這個的技巧。

我怎樣才能實現這一目標?

首先,我將創建一個幫助程序,為每個列表創建連續項集:

def create_successive_items(lst, n):
    return set(zip(*[lst[i:] for i in range(n)]))

然后,您可以根據這些集合簡單地檢查所有列表的交集:

list1 = ['a','b','c','d']
list2 = ['f','n','a','b','g']
list3 = ['x','f','g','z']
list4 = ['y','a','b','f','g','k']


lists = [list1, list2, list3, list4]

# First look for two elements
i = 2

all_found = []

while True:
    # find all "i" successive items in each list as sets
    succ = [create_successive_items(lst, i) for lst in lists]
    founds = []
    # Check for matches in different lists
    for list_number1, successives1 in enumerate(succ, 1):
        # one only needs to check all remaining other lists so slice the first ones away
        for list_number2, successives2 in enumerate(succ[list_number1:], list_number1+1):
            # Find matches in the sets with intersection
            inters = successives1.intersection(successives2)
            # Print and save them
            if inters:
                founds.append((inters, list_number1, list_number2))
                print(list_number1, list_number2, inters)

    # If we found matches look for "i+1" successive items that match in the lists
    # One could also discard lists that didn't have "i" matches, but that makes it
    # much more complicated.
    if founds:
        i += 1
        all_found.append(founds)
    # no new found, just end it
    else:  
        break

這打印匹配:

1 2 {('a', 'b')}
1 4 {('a', 'b')}
2 4 {('a', 'b')}
3 4 {('f', 'g')}

這些也可以在all_founds ,可以使用和/或轉換,即轉換為dict

matches = {}
for match, idx1, idx2 in all_found[0]:
    matches.setdefault(idx1, []).append(idx2)
    matches.setdefault(idx2, []).append(idx1)

>>> matches
{1: [2, 4], 
 2: [1, 4], 
 3: [4], 
 4: [1, 2, 3]}

通過使用元組集,您可以獲得一些樂趣。 因為元組是可以清除的,所以你需要的是幾個輔助函數來從給定列表中獲取所有連續排序的子列表,並且可以使用set intersection進行比較。

from itertools import permutations
def radix(rg, n_len):
    """
    Returns all ordered sublists of length n_len from
    the list rg
    :type rg: list[char]
    :type n_len: int
    """
    for x in range(0, len(rg) - n_len + 1):
        yield tuple(rg[x:x + n_len])

def all_radixes(rg):
    """
    Returns all ordered sublists of length 2 or longer
    from the given list
    :type rg: list[char]
    """
    for x in range(2, len(rg) + 1):
        for result in radix(rg, x):
            yield result

def compare_lists(rg1, rg2):
    s1 = set(all_radixes(rg1))
    s2 = set(all_radixes(rg2))
    return s1 & s2

list1 = 'a,b,c,d'.split(',')
list2 = 'f,n,a,b,g'.split(',')
list3 = 'x,f,g,z'.split(',')
list4 = 'y,a,b,f,g,k'.split(',')

all_lists = [ list1, list2, list3, list4 ]
for z in permutations(all_lists, 2):
    print 'Intersection of %s and %s: %s' % (z[0], z[1], compare_lists(z[0], z[1]),)

暫無
暫無

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

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