【问题标题】:Slice a list such that the result has the 2 elements before and 2 elements after the subject and a constant result length?对列表进行切片,使得结果在主题之前有 2 个元素,在主题之后有 2 个元素,并且结果长度不变?
【发布时间】:2020-06-05 12:07:02
【问题描述】:

给定这个排序数组:

>>> x = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l']

我想对这个数组进行切片,以便始终有 5 个元素。上面 2 个,下面 2 个。我去了:

>>> [x[i-2:i+2] for i, v in enumerate(x)]

这会导致:

[[], [], ['a', 'b', 'c', 'd'], ['b', 'c', 'd', 'e'], ['c', 'd', 'e', 'f'], ['d', 'e', 'f', 'g'], ['e', 'f', 'g', 'h'], ['f', 'g', 'h', 'i'], ['g', 'h', 'i', 'j'], ['h', 'i', 'j', 'k'], ['i', 'j', 'k', 'l'], ['j', 'k', 'l']]

这样做的问题是:

  1. 每组有 4 个元素,而不是 5 个
  2. 并非每个组都有 2 个以上和 2 个以下。
  3. 第一组和最后一组是特殊情况。我不想 前面的空白。我想看到的是['a', 'b', 'c', 'd', 'e'] 作为第一组,然后是['b', 'c', 'd', 'e', 'f'] 作为第二组。

我也玩过夹住切片。

首先我defined a clamp function是这样的:

>>> def clamp(n, smallest, largest): return max(smallest, min(n, largest))

然后,我这样应用函数:

>>> [x[clamp(i-2, 0, i):clamp(i+2, i, len(x))] for i, v in enumerate(x)]

但结果并没有那么好:

[['a', 'b'], ['a', 'b', 'c'], ['a', 'b', 'c', 'd'], ['b', 'c', 'd', 'e'], ['c', 'd', 'e', 'f'], ['d', 'e', 'f', 'g'], ['e', 'f', 'g', 'h'], ['f', 'g', 'h', 'i'], ['g', 'h', 'i', 'j'], ['h', 'i', 'j', 'k'], ['i', 'j', 'k', 'l'], ['j', 'k', 'l']]

我是不是在正确地吠叫?

我找到了两篇关于这个问题的 SO 文章,但它们没有解决这些极端情况:

Search a list for item(s)and return x number of surrounding items in python

efficient way to find several rows above and below a subset of data

【问题讨论】:

  • 你在寻找这样的东西吗[x[i-2:i+3] for i in range(2, len(x) - 2)] 另外为什么不在主题之后做 4 个元素呢? [x[i:i+5] for i in range(len(x) - 4)]

标签: python


【解决方案1】:

几个观察:

您可能想要使用 range(len(x)) 而不是枚举,那么您将避免解包结果。

如果有人需要了解切片符号,this may help

然后,您可以在推导式中过滤列表

x = list('abcdefghijklmno')
[ x[i-2:i+2+1] for i in range(len(x)) if len(x[i-2:i+2+1]) == 5 ]
# [['a', 'b', 'c', 'd', 'e'], ['b', 'c', 'd', 'e', 'f'], ['c', 'd', 'e', 'f', 'g'], ['d', 'e', 'f', 'g', 'h'], ['e', 'f', 'g', 'h', 'i'], ['f', 'g', 'h', 'i', 'j'], ['g', 'h', 'i', 'j', 'k'], ['h', 'i', 'j', 'k', 'l'], ['i', 'j', 'k', 'l', 'm'], ['j', 'k', 'l', '`
# On python 3.8 you can use the walrus operator!!!
[ y for i in range(len(x)) if len(y:=x[i-2:i+2+1]) == 5 ]
# [['a', 'b', 'c', 'd', 'e'], ['b', 'c', 'd', 'e', 'f'], ['c', 'd', 'e', 'f', 'g'], ['d', 'e', 'f', 'g', 'h'], ['e', 'f', 'g', 'h', 'i'], ['f', 'g', 'h', 'i', 'j'], ['g', 'h', 'i', 'j', 'k'], ['h', 'i', 'j', 'k', 'l'], ['i', 'j', 'k', 'l', 'm'], ['j', 'k', 'l', 'm', 'n'], ['k', 'l', 'm', 'n', 'o']]

【讨论】:

  • 海象运算符!是的!
  • 回答这个问题只是一个借口。中心点是提到海象操作员。对于未来好奇的访客:python.org/dev/peps/pep-0572
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-16
  • 2013-07-12
  • 2011-09-30
  • 1970-01-01
  • 2018-10-17
  • 2020-12-18
相关资源
最近更新 更多