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

时间:2015-03-30 21:59:24

标签: python string list

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

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

我必须找到有多少列表具有相同的元素。例如,对于元素['AB','A0'],上面列表的正确结果是3,因为它是连接大多数元素的元素。

我写了一些代码......但它并不好......它适用于列表中的2个列表,但不是更多.... 请帮忙! 这是我的代码......对于上面的列表...

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             

5 个答案:

答案 0 :(得分:2)

由于您的数据结构相当复杂,您可能希望构建一个递归函数,这是一个自我调用的函数(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)

答案 1 :(得分:1)

这是一种迭代方法,也可以使用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

答案 2 :(得分:0)

Ooookay - 这可能不是一个非常好的和简单的代码,但这就是我试图解决这个问题的方法。请不要伤害我; - )

<强>首先,

我将问题分成三个较小的问题:

  1. 摆脱多个嵌套列表,
  2. 计算内部列表和
  3. 中所有值对的出现次数
  4. 从计数结果中提取最常出现的值对。
  5. <强> 1

    我仍然使用嵌套列表,但只使用两级深度。外部列表,迭代,以及其中的所有两个值列表。您可以获得有关如何摆脱嵌套列表 right here 的大量信息。由于我只是一个初学者,我无法从所有非常详细的信息中做出太多贡献 - 但如果向下滚动,你会发现一个类似于我的例子。这就是我的理解,这就是我能做的。

    请注意,它是一个递归函数。正如你在评论中提到的,你认为这不容易理解:我认为你是对的。我会尝试以某种方式解释它:

    我不知道您的列表中的嵌套深度是否一致。并且我不想将值本身提取出来,因为您希望使用列表。所以这个函数循环遍历外部列表。对于每个元素,它会检查它是否为列表。如果没有,没有任何反应。如果它是一个列表,它将查看该列表中的第一个元素。它会再次检查它是否是一个列表。

    如果当前列表中的第一个元素是另一个列表,则将再次调用该函数 - 递归 - 但这次是从当前内部列表开始。重复此过程,直到函数找到一个列表,其中包含第一个位置上不是列表的元素。

    在您的示例中,它将深入查看完整的列表列表,直到找到您的第一个字符串值。然后它获取包含该值的列表 - 并将其放入另一个列表中,即返回的列表。

    哦,小伙子,听起来真的很疯狂 - 告诉我,如果澄清了什么...... :-D

    “哟dawg,我喜欢你喜欢的列表,所以我把列表放在列表中......”

    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']
    

    的Ta-DAA! : - )

    如果您确实只有9个元素的列表,并且您不需要经常计算值 - 手动执行。通过读取值并用手指计数。它会变得如此简单; - )

    否则,你走吧!

    或...

    ...你等到一些Guru出现并给你一个我以前从未见过的超快速,优雅的单行蟒蛇命令,它会做同样的事情; - )

答案 3 :(得分:0)

这很简单,我可以合理地做到:

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() generate会生成一系列排序元组,表示列表中的每个项目。 Counter对象计算每个对象的出现次数,其.most_common(1)方法返回最常见项的值和计数。

你说过递归太难了,但我不同意见:这是解决这个问题的最简单方法。你越早来爱递归,你就越快乐。 : - )

答案 4 :(得分:-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;