简体   繁体   English

垂直或水平地在列表列表中“连续”计数值

[英]Counting values “in a row” in list of lists vertically or horizontally

I'm writing a function that counts the number of occurrences of a specific value of a list of lists in a row whether horizontal or vertical. 我正在编写一个函数,该函数计算水平或垂直行中列表列表的特定值的出现次数。 Then it just needs to return the value of how many times it occurred. 然后,它只需要返回发生多少次的值即可。 Here's an example 这是一个例子

lst=[['.','.','.','e'],
     ['A','A','.','e'],
     ['.','.','.','e'],
     ['.','X','X','X'],
     ['.','.','.','.'],
     ['.','.','.','e']]

For this list of lists, the function should return 3 for e as it appears 3 times in a row, 2 for A, and 3 for X. Thank you for your time 对于此列表列表,该函数应该连续返回3次,使e返回3,对于A,返回2,对于X,返回3。感谢您的时间

My code so far: 到目前为止,我的代码:

def length_of_row(symbol,lot):
    count = 0
    for sublist in lot:
        for x in sublist:
            if x == symbol:
                count += 1
                continue
            else:
                continue
                return count

This is actually quite a messy problem to solve with basic principles, and will be especially hard if you've just started learning programming. 用基本原理解决这实际上是一个很麻烦的问题,如果您刚刚开始学习编程,它将尤其困难。 Here's a concise but more advanced solution: 这是一个简洁但更高级的解决方案:

result = {}
for grid in [lst, zip(*lst)]:
    for row in grid:
        for key, group in itertools.groupby(row):
            result[key] = max(len(list(group)), result.get(key, 0))

Then result is: 那么result是:

{'A': 2, 'X': 3, 'e': 3, '.': 4}

You can try the following if you don't mind changing things a little bit: 如果您不介意进行一些更改,可以尝试以下操作:

from functools import reduce
from itertools import takewhile


def length_of_row(symbol, lot):
    if symbol not in reduce(lambda x,y: x+y, lot):
        return 0
    elif symbol in lot[0]:
        good_lot =  map(lambda y: y.count(symbol),takewhile(lambda x: symbol in x, lot))
        return sum(good_lot)
    else:
        return length_of_row(symbol, lot[1:])

This uses a combination of recursion and one of python's powerful itertools methods ( takewhile ). 这结合了递归和python强大的itertools方法之一( takewhile )。 The idea is to count the number of symbols until you hit a list that does not contain that symbol. 这个想法是计算符号的数量,直到您点击不包含该符号的列表。 Also, it tries to make sure that it only counts the occurrences of the symbol if said symbol is in the list of lists. 另外,它试图确保仅在符号出现在列表列表中时才计算符号的出现次数。

Using it: 使用它:

lst = [['.', '.', '.', 'e'],
 ['A', 'A', '.', 'e'],
 ['.', '.', '.', 'e'],
 ['.', 'X', 'X', 'X'],
 ['.', '.', '.', '.'],
 ['.', '.', '.', 'e']]

print(length_of_row('e', lst))
print(length_of_row('X', lst))
print(length_of_row('A', lst))
print(length_of_row('f', lst))

#3
#3
#2
#0

As you can see, if the symbol does not exist it returns 0 . 如您所见,如果该符号不存在,它将返回0

Edit: 编辑:

If you don't wish to import the takewhile function from itertools , you can use the approximate definition provided in the documentation. 如果您不想从itertools导入takewhile函数,则可以使用文档中提供的近似定义。 But just keep in mind that it is not as optimized as the itertools method: 但是请记住,它的优化程度不如itertools方法:

def takewhile(predicate, iterable):
    for x in iterable:
        if predicate(x):
            yield x
        else:
            break

Also, reduce should be available to you directly if you are using python2 . 另外,如果您正在使用python2 ,则reduce应该直接对您可用。 However, you can define a function to reduce a list of lists into one list as follows: 但是,您可以定义一个将列表列表简化为一个列表的函数,如下所示:

def reduce_l_of_l(lst_of_lst):
    out_lst = []
    for lst in lst_of_lst:
        out_lst += lst
    return out_lst

Instead of using reduce , just replace it with reduce_l_of_l after it's been defined. 无需使用reduce ,只需在定义后将其替换为reduce_l_of_l

I hope this helps. 我希望这有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM