【问题标题】:Counting values "in a row" in list of lists vertically or horizontally垂直或水平计算列表列表中“连续”的值
【发布时间】:2017-03-14 01:53:15
【问题描述】:

我正在编写一个函数来计算列表列表中特定值的出现次数连续水平或垂直。然后它只需要返回它发生了多少次的值。这是一个例子

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

对于这个列表列表,函数应该为 e 返回 3,因为它连续出现 3 次,为 A 为 2,为 X 为 3。谢谢您的时间

到目前为止我的代码:

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

【问题讨论】:

  • 您在代码中的哪个位置测试符号是否相同?
  • 我认为你不明白 continue 做了什么。在这里无法联系到return count
  • 您的代码甚至不检查数组中的元素是否是传递给函数的符号。它所做的只是计算真实值的数量。
  • return count 的缩进几乎肯定是错误的,它可能意味着在循环之外。
  • @Barmar 特定列表(如我上面包含的“lst”)被输入到函数中,然后它测试“符号”(可以是任何字符)连续出现的次数是否垂直或水平。对于那个特定的,它测试 A 并应返回 2 并测试 C 应返回 0,因为该列表列表中没有 C

标签: python list python-3.x count symbols


【解决方案1】:

如果您不介意稍作改动,可以尝试以下方法:

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:])

这结合了递归和 python 强大的itertools 方法之一 (takewhile)。这个想法是计算符号的数量,直到您点击一个不包含该符号的列表。此外,它会尝试确保仅当符号在列表列表中时才计算符号的出现次数。

使用它:

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

如您所见,如果符号不存在,则返回0

编辑:

如果您不想从itertools 导入takewhile 函数,您可以使用文档中提供的近似定义。但请记住,它不如itertools 方法优化:

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

此外,如果您使用的是python2,您应该可以直接使用reduce。但是,您可以定义一个函数来将列表列表缩减为一个列表,如下所示:

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

不要使用reduce,而是在定义后将其替换为reduce_l_of_l

我希望这会有所帮助。

【讨论】:

  • 非常感谢我选择这个作为最佳答案,因为它以正确的方式返回。如果不导入模块,这仍然可能吗?我应该在最初的问题中说清楚,但其中的一部分挑战不是导入工具(不知道为什么这么说,因为它只会让事情变得更加困难)
  • 我在网上找到了 reduce 的定义并将其添加到我的程序中,现在它可以工作了,非常感谢您的大力帮助
  • 我很高兴这很有用。
【解决方案2】:

这实际上是一个很难用基本原理解决的问题,如果您刚开始学习编程,这将尤其困难。这是一个简洁但更高级的解决方案:

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))

那么result就是:

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

【讨论】:

  • 感谢您的回答。这可以在不导入模块的情况下完成,而是只返回正在测试的字符的特定值吗?如果您不想编写代码但也许可以解释如何在不导入的情况下完成它会很有帮助。例如,结果等于 2、3、3 或 4,具体取决于它是在测试 A、X、e 还是“。” .
猜你喜欢
  • 1970-01-01
  • 2012-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-14
  • 2019-07-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多