簡體   English   中英

查找列表中有多少個列表具有相同的元素

[英]Find how many lists in list have the same element

我是Python的新手,所以遇到了一些麻煩。 我在一個列表中有幾個字符串列表。

list=[  [['AA','A0'],['AB','A0']],
        [['AA','B0'],['AB','A0']],
        [['A0','00'],['00','A0'], [['00','BB'],['AB','A0'],['AA','A0']] ]
     ]

我必須找到多少個具有相同元素的列表。 例如,對於上面的列表,元素['AB','A0']的正確結果是3,因為它是連接大部分元素的元素。

我寫了一些代碼...但是不好...它適用於列表中的兩個列表,但不適用於更多...。請幫助! 這是我的代碼...上面的清單...

for t in range(0,len(list)-1):
     pattern=[]
     flag=True
     pattern.append(list[t])
     count=1
     rest=list[t+1:]
     for p in pattern:
         for j in p:
            if flag==False:
               break
            pair= j
            for i in rest:
                 for y in i:
                    if pair==y:
                        count=count+1
                          break                   
            if brojac==len(list):
                flag=False
                    break             

由於您的數據結構相當復雜,因此您可能需要構建一個遞歸函數,該函數可以自我調用( http://en.wikipedia.org/wiki/Recursion_(computer_science) )。

此功能非常簡單。 您遍歷原始列表的所有項目。 如果當前項目等於要搜索的值,則將找到的對象數增加1。如果該項目本身是列表,則將遍歷該子列表並在該子列表中找到所有匹配項(通過在子列表而不是原始列表上調用相同的函數)。 然后,您可以通過子列表中的計數來增加找到的對象的總數。 我希望我的解釋是清楚的。

alist=[[['AA','A0'],['AB','A0']],[['AA','B0'],['AB','A0']],[['A0','00'],['00','A0'],[['00','BB'],['AB','A0'],['AA','A0']]]]

def count_in_list(val, arr):
    val_is_list = isinstance(val, list)
    ct = 0
    for item in arr:
        item_is_list = isinstance(item, list)
        if item == val or (val_is_list and item_is_list and sorted(item) == sorted(val)):
            ct += 1
        if item_is_list :
            ct += count_in_list(val, item)
    return ct

print count_in_list(['AB', 'A0'], alist)

這是一種迭代方法,也可以使用python3來工作,該方法將獲取所有子列表的計數:

from collections import defaultdict

d = defaultdict(int)

def counter(lst,  d):
    it = iter(lst)
    nxt = next(it)
    while nxt:
        if isinstance(nxt, list):
            if nxt and isinstance(nxt[0], str):
                d[tuple(nxt)] += 1
                rev = tuple(reversed(nxt))
                if rev in d:
                    d[rev] += 1
            else:
                 lst += nxt
        nxt = next(it,"")
    return d


print((counter(lst, d)['AB', 'A0'])
3

僅適用於像您的輸入這樣的數據,列表旁邊的字符串嵌套會破壞代碼。

要獲得單個子列表計數更容易:

def counter(lst,  ele):
    it = iter(lst)
    nxt = next(it)
    count = 0
    while nxt:
        if isinstance(nxt, list):
            if ele in (nxt, nxt[::-1]):
                count += 1
        else:
            lst += nxt
        nxt = next(it, "")
    return count

print(counter(lst, ['AB', 'A0']))
3

糟糕-這可能不是很好的代碼,但是這就是我要嘗試解決的方式。 請不要傷害我;-)

第一,

我將問題分成三個較小的部分:

  1. 擺脫多個嵌套列表,
  2. 計算內部列表中所有值對的出現,並
  3. 從計數結果中提取最常出現的值對。

1。

我仍然會使用嵌套列表,但是深度只有兩層。 要遍歷的外部列表及其內部的所有兩個值列表。 您可以在此處找到有關如何清除嵌套列表的大量信息。 因為我只是一個初學者,所以我無法從所有非常詳細的信息中受益匪淺-但如果向下滾動,您會發現一個與我相似的示例。 這就是我的理解,這就是我的能力。

請注意,這是一個遞歸函數。 正如您在評論中提到的那樣,您認為這不容易理解:我認為您是對的。 我將嘗試以某種方式進行解釋:

我不知道嵌套深度在您的列表中是否一致。 而且我不想自己提取值,因為您想使用列表。 因此,此函數遍歷外部列表。 對於每個元素,它都會檢查它是否是一個列表。 如果沒有,則什么也不會發生。 如果它是一個列表,則將查看該列表中的第一個元素。 它將再次檢查它是否為列表。

如果當前列表中的第一個元素是另一個列表,則將再次調用該函數-遞歸-但這一次從當前內部列表開始。 重復此操作,直到函數找到一個列表,該列表在第一個位置上包含一個不是列表的元素。

在您的示例中,它將遍歷完整的列表列表,直到找到您的第一個字符串值。 然后,它獲取包含該值的列表-並將其放在另一個列表中,然后返回該列表。

哦,男孩,這聽起來真是太瘋狂了-告訴我是否可以澄清任何事情... :-D

“喲,我想你喜歡清單,所以我把清單放在清單里……”

def get_inner_lists(some_list):
    inner_lists = []
    for item in some_list:
        if hasattr(item, '__iter__') and not isinstance(item, basestring):
            if hasattr(item[0], '__iter__') and not isinstance(item[0], basestring):
                inner_lists.extend(get_inner_lists(item))
            else:
                inner_lists.append(item)                            
    return inner_lists

無論如何-調用該函數,您會發現列表重新排列了一下:

>>> foo = [[['AA','A0'],['AB','A0']],[['AA','B0'],['AB','A0']],[['A0','00'],['00','A0'],[['00','BB'],['AB','A0'],['AA','A0']]]]
>>> print get_inner_lists(foo)

[['AA', 'A0'], ['AB', 'A0'], ['AA', 'B0'], ['AB', 'A0'], ['A0', '00'], ['00', 'A0'], ['00', 'BB'], ['AB', 'A0'], ['AA', 'A0']]

2。

現在,我將遍歷該列表並使用其值構建一個字符串。 這僅適用於兩個值的列表,但是正如您在示例中所顯示的那樣。 在迭代時,我將建立一個字典,將字符串作為鍵,將出現的值作為值。 這使得添加新值和增加現有值的計數器非常容易:

def count_list_values(some_list):
    result = {}
    for item in some_list:
        str = item[0]+'-'+item[1]
        if not str in result.keys():
            result[str] = 1
        else:
            result[str] += 1    
    return result

在那里,所有計數都已完成。 我不知道是否需要它,但是副作用是所有值和所有情況都出現了:

>>> print count_list_values(get_inner_lists(foo))

{'00-A0': 1, '00-BB': 1, 'A0-00': 1, 'AB-A0': 3, 'AA-A0': 2, 'AA-B0': 1}

3。

但是您想要清晰的結果,因此讓我們循環瀏覽該字典,列出所有鍵和所有值,找到最大值-並返回相應的鍵。 用分隔符( - )構建兩個值的字符串后,很容易將其拆分並再次列出該列表:

def get_max_dict_value(some_dict):
    all_keys = []
    all_values = []
    for key, val in some_dict.items():
        all_keys.append(key)
        all_values.append(val)
    return all_keys[all_values.index(max(all_values))].split('-')

如果定義了這三個小功能,然后將它們組合使用,那么您將獲得:

>>> print get_max_dict_value(count_list_values(get_inner_lists(foo)))

['AB', 'A0']

塔達! :-)

如果您確實有這樣的列表,其中僅包含9個元素,並且您不需要經常計算值-則手動進行。 通過讀取值並用手指計數。 這樣會容易得多;-)

否則,你去!

要么...

...您等到某個Guru出現並給您一個我從未見過的超快速,優雅的單行python命令時,它將執行相同的操作;-)

這很簡單,我可以合理地做到:

from collections import Counter

lst = [  [['AA','A0'],['AB','A0']],
        [['AA','B0'],['AB','A0']],
        [['A0','00'],['00','A0'], [['00','BB'],['AB','A0'],['AA','A0']] ]
     ]


def is_leaf(element):
    return (isinstance(element, list) and
            len(element) == 2 and
            isinstance(element[0], basestring)
            and isinstance(element[1], basestring))


def traverse(iterable):
    for element in iterable:
        if is_leaf(element):
            yield tuple(sorted(element))
        else:
            for value in traverse(element):
                yield value

value, count = Counter(traverse(lst)).most_common(1)[0]
print 'Value {!r} is present {} times'.format(value, count)

traverse()生成產生一系列已排序的元組,它們表示列表中的每個項目。 Counter對象對每個對象的出現次數進行計數,其.most_common(1)方法返回最常見項目的值和計數。

您已經說過遞歸太困難了,但是我希望有所不同:這是解決此問題的最簡單方法。 您越早喜歡遞歸,就會越快樂。 :-)

希望這樣的東西就是您想要的。 這有點脆弱,建議遞歸更好。 但是由於您不希望這樣,所以這里有一些代碼可能會起作用。 我不太擅長python,但希望它能勝任:

def Compare(List):
    #Assuming that the list input is a simple list like ["A1","B0"]
    myList =[[['AA','A0'],['AB','A0']],[['AA','B0'],['AB','A0']],[['A0','00'],['00','A0'],[['00','BB'],['AB','A0'],['AA','A0']]]]

#Create a counter that will count if the elements are the same
myCounter = 0;
for innerList1 in myList:        
    for innerList2 in innerList1
        for innerList3 in innerList2
            for element in innerList3
                for myListElements in myList
                    if (myListElements == element)
                        myCounter = myCounter + 1;

                        #I am putting the break here so that it counts how many lists have the
                        #same elements, not how many elements are the same in the lists
                        break;

return myCounter;

暫無
暫無

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

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