【问题标题】:How to pick a sequence of numbers from a list?如何从列表中选择一个数字序列?
【发布时间】:2017-01-25 04:37:17
【问题描述】:

我有一个起始编号和一个结束编号。
我需要从这些数字中选择一个数字序列。
序列并不总是相同的。

例子:

startnumber = 1
endnumber = 32

我需要创建一个具有特定顺序的数字列表
体育
3个数字是,2个数字没有,3个数字是,2个数字没有..等等

预期输出:

[[1-3],[6-8],[11-13],[16-18],[21-23],[26-28],[31-32]]

(最后只剩下2个数字(31和32))

在 python 中是否有一种简单的方法可以从一系列数字中选择行序列?

【问题讨论】:

  • 我假设 [1-3] 你的意思是 [1,2,3]
  • 我不明白你是如何定义序列的。 “不总是一样”是指随机的吗?每次绘制的序列数必须相同吗?
  • 谁来决定“Take 3, drop 2, take 3, drop 2, ...”的顺序?
  • @PatrickHaugh,我的意思是从 1 到 3 的数字 [1-3]
  • @yogabonito i%5 not in (0, 4)

标签: python list python-3.x filter sequence


【解决方案1】:
numbers = range(1,33)
take = 3
skip = 2
seq = [list(numbers[idx:idx+take]) for idx in range(0, len(numbers),take+skip)]

【讨论】:

  • 这很聪明。只需稍微编辑一下,使 take 3, drop 2 模式可见和可自定义,并隐藏将 33 转换为 35 的技巧☺
  • 这似乎是 Python 2。在 Python 3(标记的那个)中,可以将 range 转换为 list
  • 谢谢,这是一个很好的解决方案。然而,它给出了一个包含范围和元组[range(1, 4), range(6, 9), range(11, 14), range(16, 19), range(21, 24), range(26, 29), range(31, 33)] 的输出,并且范围中的第二个值不是我所期望的。
  • 对不起。我刚刚看到@Ev.Kounis 在上面指出的python-3.x 标签。我已经编辑了答案以将范围转换回列表。
  • @Reman 先跳过seq =[list(numbers[idx+skip:idx+take+skip]) for idx in range(0, len(numbers)-skip,take+skip)]
【解决方案2】:

推断出来:

def get_data(data, filterfunc=None):
    if filterfunc is None:
        filterfunc = lambda: True  # take every line

    result = []
    sub_ = []
    for line in data:
        if filterfunc():
            sub_.append(line)
        else:
            if sub_:
                result.append(sub_)
                sub_ = []

    return result

# Example filterfunc
def example_filter(take=1, leave=1):
    """example_filter is a less-fancy version of itertools.cycle"""

    while True:
        for _ in range(take):
            yield True
        for _ in range(leave):
            yield False

# Your example
final = get_data(range(1, 33), example_filter(take=3, leave=2))

正如在 example_filter 的文档字符串中所提到的,get_data 的 filterfunc 实际上只是期望基于调用的 TrueFalse。您可以轻松地将其更改为签名:

def filterfunc(some_data: object) -> bool:

这样您就可以根据值(甚至索引)确定是接受还是离开,但它目前不接受任何参数,只是作为一个不那么神奇的itertools.cycle(因为它应该在调用时返回它的值,不在迭代中)

【讨论】:

    【解决方案3】:
    from itertools import islice
    def grouper(iterable, n, min_chunk=1):
        it = iter(iterable)
        while True:
           chunk = list(islice(it, n))
           if len(chunk) < min_chunk:
               return
           yield chunk
    
    def pick_skip_seq(seq, pick, skip, skip_first=False):
        if skip_first:
            ret = [ x[skip:] for x in grouper(seq, pick+skip, skip+1) ]
        else:
            ret = [ x[:pick] for x in grouper(seq, pick+skip) ]
        return ret
    

    pick_skip_seq(range(1,33), 3, 2) 提供所需的列表。

    pick_skip_seq(seq, pick, skip, skip_first=False)seq 是从中选择/跳过的序列, pick/skip 没有。要选择/跳过的元素, skip_first 将被设置为 True 如果 这种行为是需要的。

    grouper 返回 n 个元素的块,它 如果最后一组较少,则忽略它 比 min_chunk 元素。 它来源于给出的东西 https://stackoverflow.com/a/8991553/1921546.

    演示:

    # pick 3 skip 2 
    for i in range(30,35):
        print(pick_skip_seq(range(1,i), 3, 2))
    
    # skip 3 pick 2 
    for i in range(30,35):
        print(pick_skip_seq(range(1,i), 3, 2, True))
    

    pick_skip_seq 的替代实现:

    from itertools import chain,cycle,repeat,compress
    def pick_skip_seq(seq, pick, skip, skip_first=False):
        if skip_first:
            c = cycle(chain(repeat(0, skip), repeat(1, pick)))
        else:
            c = cycle(chain(repeat(1, pick), repeat(0, skip)))
        return list(grouper(compress(seq, c), pick))
    

    所有使用的东西都记录在这里:https://docs.python.org/3/library/itertools.html#itertools.compress

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-30
      • 1970-01-01
      相关资源
      最近更新 更多