【问题标题】:Pythonesque way to compare adjacent elements in a list [duplicate]比较列表中相邻元素的Pythonesque方法[重复]
【发布时间】:2021-04-28 20:07:13
【问题描述】:

我很确定这个问题已经被问了无数次,但我找不到令人满意的答案。我试图遍历一个列表并找出'B' 有多少次出现在'A' 之前。我有一个解决方案,但我确信它远非完美。在 C++ 中,我会做类似的事情(大约有 10 种变体):

int main()
{
    vector<char> charList={'A', 'B', 'D', 'B', 'C', 'A', 'B'};
    int count=0;
    char prevElem = '\0';
    for(auto x: charList)
    {
        if( x == 'B' && prevElem =='A')
            ++count;
        prevElem = x;
    }
    
    cout << "Count = " << count << endl;

    return 0;
}

在 Python 中正确的做法是什么? 我的意思是最简单的解决方案是显而易见的,但是如果我拥有的数据是迭代器的形式,并且我不想重复该迭代器两次,我该怎么办?

【问题讨论】:

  • 你试过用 Python 写同样的算法吗?
  • 是的,这就是我所说的“远非完美”的意思。我的问题有点复杂:如果我拥有的数据是迭代器的形式,它下面有惰性迭代器并且我不想重复该迭代器两次,我该怎么办?
  • 您可以在 C++ 代码中做同样的事情。
  • 解决此类问题的好地方是itertools recipes,在本例中为pairwise。 (sum(map(lambda cc:cc==('A', 'B'), pairwise(charlist))))。与使用下标或切片的解决方案不同,这将适用于任意序列,包括生成器。
  • @rici map(lambda) 很丑。生成器表达式更好更短:sum(cc==('A', 'B') for cc in pairwise(charlist))

标签: python python-3.x iterator


【解决方案1】:

Robot Jung 的回答我的版本:

def findAb(data):
    iterator = iter(data)
    prevElem = ''

    for curElem in iterator:
        yield int(curElem == 'B' and prevElem == 'A')
        prevElem = curElem

if __name__ == '__main__':
    data =  ['A', 'B', 'D', 'B', 'C', 'A', 'B']

    count = sum( d for d in findAb(data))
    print (count)

【讨论】:

  • 与 RobertJung 给出的更简单、更清晰的解决方案(即第二个)相比,这有何改进?
  • 我稍微清理了一下,请再检查一下。我不知道这是否是一种改进。还在学习。我想这只是让用户更容易看到意图
  • 在新版本中:为什么不增加 findAb 内的计数并返回呢?这里不需要生成器函数。
  • 也许你是对的。可用工具太多
【解决方案2】:

试试这个代码:

char_list = ['A', 'B', 'D', 'B', 'C', 'A', 'B']

count = 0
for index in range(0, len(char_list)-1):
    if char_list[index] == 'A' and char_list[index+1] == 'B':
        count += 1

print('count :', count)

试试这个新的:

char_list = ['A', 'B', 'D', 'B', 'C', 'A', 'B', 'A', 'B']
prev_char = ''

count = 0
for char in char_list:
    if char == 'B' and prev_char == 'A':
        count += 1
    prev_char = char

print('count :', count)

【讨论】:

  • 这就是我现在所拥有的。我的问题有点复杂:如果我拥有的数据是迭代器的形式,它下面有惰性迭代器并且我不想重复该迭代器两次,我该怎么办?
  • @MarkZ 你真的应该把这些信息放在问题中。
  • 如果列表以 'A' 结尾,这将引发 IndexError。
  • @MarkZ 我添加了一个新答案,请查看它。
  • 是的,这就是我要找的。我更进一步。也请参阅我自己的答案
【解决方案3】:

最简单的实现如下:

array = ['A', 'B', 'D', 'B', 'C', 'A', 'B']

count = 0
for i in range(len(array)-1):
  if array[i] == 'A' and array[i+1] == 'B':
    count += 1

print(count)

【讨论】:

  • 这会引发 IndexError。
  • 不,不会。因为循环运行比上限少 1 倍。而且由于索引从 0 开始到 len(array) - 1,所以它可以正常工作。
  • i 最高可达len(array)-1,因此i+1 最高可达len(array),如果数组以'A' 结尾,则会引发 IndexError。
  • 啊,我现在明白了。接得好。我编辑了帖子。
【解决方案4】:

Previus 解决方案会对以 A 结尾的列表给出错误。我建议从索引 1 开始并查看上一个

char_list = ['A', 'B', 'D', 'B', 'C', 'A', 'B']

count = 0
for index in range(1, len(char_list)):
    if char_list[index] == 'B' and char_list[index-1] == 'A':
        count += 1

print('count :', count)

【讨论】:

    猜你喜欢
    • 2019-05-05
    • 2012-05-04
    • 2019-09-06
    • 2012-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-09
    • 2021-06-25
    相关资源
    最近更新 更多