-1

我正在尝试查看具有连续元素的三个一组是否具有锯齿形图案。添加到一个空列表“1”代表之字形,“1”代表曲折,或“0”都不代表。它似乎满足了我的第一个“if”条件和我的“else”语句,但从不满足中间条件。我已经尝试将它作为两个 if 语句,一个 if 和一个 elif,并嵌套。答案应该是 [1,1,0] 但我只能得到 [1,0] 或没有输出,有时“索引超出范围”。输入 [1,2,1,3,4] 输出 [1,1,0]

    def solution(numbers):
        arr = []
        for i in range(len(numbers)-2):
            if numbers[i+1] > numbers[i] and numbers[i+2]:
                arr.append(1)
            if numbers[i+1] < numbers[i] and numbers[i+2]:
                arr.append(1)
            else:
                arr.append(0)
                return arr
4

4 回答 4

1

将解决方案分为两部分:

  1. 建立一个连续数字(之字形和锯齿形)之间差异的列表。
  2. 返回连续之字形和之字形(之字形)之间的差异列表。

您可以使用zipwith slices 来遍历每对连续元素:

def zig_zags(numbers):
    zigzags = [(a - b) // abs(a - b) for a, b in zip(numbers, numbers[1:])]
    return [int(a and b and a != b) for a, b in zip(zigzags, zigzags[1:])]

print(zig_zags([1, 2, 1, 3, 4]))  # [1, 1, 0]

为了进一步分解,让我们使用 REPL 来看看zipslice 是如何工作的:

>>> numbers = [1, 2, 1, 3, 4]
>>> numbers[1:]
[2, 1, 3, 4]
>>> [(a, b) for a, b in zip(numbers, numbers[1:])]
[(1, 2), (2, 1), (1, 3), (3, 4)]

切片[1:]从第二个元素开始获取列表,并zip获取两个列表(原始列表和偏移一的切片版本)并一次从每个列表中产生一个元素——所以总的来说,我们得到了连续的对元素。

现在让我们采用相同的表达式,但要减去 ab不是将它们变成元组:

>>> [a - b for a, b in zip(numbers, numbers[1:])]
[-1, 1, -2, -1]

负数显示原始列表在哪里减少(锯齿形),正数显示它在哪里增加(锯齿形)。(如果它既不是曲折也不是曲折,那就是零。)如果我们对曲折和曲折进行归一化,比较曲折和曲折会更容易:

>>> [(a - b) // abs(a - b) for a, b in zip(numbers, numbers[1:])]
[-1, 1, -1, -1]

现在每个“zig”都是-1,每个“zag”都是+1。所以现在让我们看看之字形跟随之字形的位置:

>>> zigzags = [(a - b) // abs(a - b) for a, b in zip(numbers, numbers[1:])]
>>> [(a, b) for a, b in zip(zigzags, zigzags[1:])]
[(-1, 1), (1, -1), (-1, -1)]
>>> [a != b for a, b in zip(zigzags, zigzags[1:])]
[True, True, False]

与之前完全相同的技术zip[1:]但现在我们正在查看我们在第一步中计算的锯齿形和锯齿形。因为我们对它们进行了标准化,所以我们需要做的就是查看它们是否彼此相等。

我们还应该明确排除没有 zigzag 的情况,即aorb为零的情况。看起来像:

>>> [a and b and a != b for a, b in zip(zigzags, zigzags[1:])]
[True, True, False]

最后,由于我们希望我们的输出是1and0而不是Trueand False,我们需要转换它。方便True的是,当您转换为时,int它会变为1False变为0,因此我们可以将整个内容包装在 中int

>>> [int(a and b and a != b) for a, b in zip(zigzags, zigzags[1:])]
[1, 1, 0]
于 2022-02-04T19:13:44.160 回答
1

您可以使用 zip 将元素 3 x 3 组合并比较每个三元组,以检查中间元素是大于其相邻元素还是小于它们两者:

numbers = [1,2,1,3,4]

result = [int((a-b)*(b-c)<0) for a,b,c in zip(numbers,numbers[1:],numbers[2:])]

print(result) # [1, 1, 0]

zip 将组合偏移 0、1 和 2 的项目,产生以下三元组:

numbers        [1,2,1,3,4]
numbers[1:]    [2,1,3,4]
numbers[2:]    [1,3,4] 
zip():          * * *   <-- 3 triplets (extras are ignored)

 a,b,c   a-b    b-c      (a-b)*(b-c)   int(...<0)
------- 
(1,2,1)  -1      1          -1            1
(2,1,3)   1     -2          -2            1 
(1,3,4)  -2     -1           2            0 
于 2022-02-04T21:47:29.550 回答
0

你这里有一个滑动窗口

你得到IndexError是因为你的代码有for i in range(len(numbers)),然后你要求numbers[i+2]. 为防止这种情况,请减小范围:

for i in range(len(numbers) - 2):
    <do checks on numbers[i], numbers[i+1], numbers[i+2]>

但是您可能更喜欢将zip一些切片放在一起:

for a, b, c in zip(numbers, numbers[1:], numbers[2:]):
    <do checks on a, b, c>
于 2022-02-04T19:13:28.453 回答
0

感谢大家!

建议我定义结束范围以避免索引超出范围错误(更改为 len(numbers)-2),并且我将格式从“numbers[i+1] < numbers[i] 和 numbers[i+2] 更改]”到“数字[i] > 数字[i+1] < 数字[i+2]”。还建议我尝试下一次我将学习的 zip 功能。

于 2022-02-05T00:42:43.930 回答