【问题标题】:How to organize data that alternates between negative and positive values in Python如何在 Python 中组织在负值和正值之间交替的数据
【发布时间】:2013-08-16 20:12:08
【问题描述】:

我有一个文件中的数据点列表,我将其插入到我构建的链表类中。
该文件的组织方式是有一系列负值,然后是一系列来回交替的正值。 一个例子:

-2323 

-2324

-53434

-1027

-34232

 343434

 5657

 6565

 6500

-343434

-3434

-565

5845

4667

5453

98356

这种模式持续多行。每个部分的负值或正值的数量永远不会相同。

我想以某种方式分隔这些值,以便第一个列表对象包含第一组正数到负数,在这种情况下从-23236500。下一个列表对象将包含从-34343498356 的值,依此类推。

我不知道如何让 python 在读取文件时知道如何分离这些数据集。 任何帮助将不胜感激!

【问题讨论】:

  • 如果它变为 neg, 0, neg, pos 会发生什么?是一两个数据集吗?

标签: python list


【解决方案1】:
import itertools
groups = itertools.groupby(l, lambda x : x > 0)
result = [list(groups[i][1]) + list(groups[i + 1][1]) for i in range(0, len(groups), 2)]

这将首先根据元素是否为正对元素进行分组,然后将组中的相邻对组合成一个列表,然后该列表将成为结果列表的一个元素。

编辑:我一直忘记 itertools 生成的对象不像普通的可迭代对象那样工作。

如果有点混乱,以下应该实际上可以工作。

import itertools
groups = itertools.groupby(l, lambda x : x > 0)
grouplist = [[i for i in y] for (x, y) in groups]
result = [grouplist[i] + grouplist[i + 1] for i in range(0, len(grouplist), 2)]

【讨论】:

  • 我喜欢这个解决方案,但是当grouplist 是一个奇数长度时,它不会得到IndexError 吗?将iter(grouplist) 的相同实例传递给izip_longest(iter_grouplist, iter_grouplist, fillvalue=[]) 可能更好?
  • 我试图避免过度使用 itertools 对象。这可以工作,或者可以通过在最后两行设置 grouplist = grouplist + [[]] if len(grouplist) % 2 else grouplist 之间插入一行来完成。
【解决方案2】:
def takeSection(sequence):
    it = iter(sequence)
    a = -1
    group = []
    while True:
        try:
            a, last = next(it), a
        except StopIteration:
            if group:
                yield group
            return
        if a < 0 and last >= 0:
            if group:
                yield group
            group = [a]
        else:
            group.append(a)

>>> sequence = [-2323, -2324, -53434, -1027, -34232, 343434, 5657, 6565, 6500, -343434, -3434, -565, 5845, 4667, 5453, 98356]
>>> list(takeSection(sequence))
Out[2]: 
[[-2323, -2324, -53434, -1027, -34232, 343434, 5657, 6565, 6500],
 [-343434, -3434, -565, 5845, 4667, 5453, 98356]]

编辑

如果您想对一对值中的第一个值进行过滤,您可以更改 if 条件来测试它。例如,您可以将条件行更改为if a[0] &lt; 0 and last[0] &gt;=0,并且还需要将a 初始化为a = (-1, -1)

不过,我很想创建一个更通用、更有用的函数。

def sections(sequence, key):
    it = iter(sequence)
    a = placeholder = object()
    group = []
    while True:
        try:
            a, last = next(it), a
        except StopIteration:
            if group:
                yield group
            return
        if last is not placeholder and key(a, last):
            if group:
                yield group
            group = [a]
        else:
            group.append(a)

>>> sequence = [(-2323, -7465), (-2324, -7687), (-53434, -1027), (-34232, 343434), (5657, 6565), (6500, 978987), (-343434, -987), (-3434, -565), (-98, -8798), (-89898, -898), (5845, 4667), (5453, 98356)]
>>> list(sections(sequence, key=lambda current, last: current[0] < 0 and last[0] >= 0))
Out[1]:
[[(-2323, -7465), (-2324, -7687), (-53434, -1027), (-34232, 343434), (5657, 6565), (6500, 978987)],
 [(-343434, -987), (-3434, -565), (-98, -8798), (-89898, -898), (5845, 4667), (5453, 98356)]]

【讨论】:

  • 谢谢,这段代码可以正常工作 但是,如果序列是 (x,y) 点的格式怎么办?例如:序列 = [(-2323, -7465), (-2324, -7687), (-53434, -1027), (-34232, 343434), (5657, 6565), (6500, 978987) (- 343434, -987) (-3434, -565), (-98, -8798), (-89898, -898), (5845, 4667), (5453, 98356)] 每个部分仍将根据每个点的负/正第一个值(x 值)。对原始问题的更改感到抱歉,但是当我尝试将您的答案应用于此案例时,我无法使其正常工作。
猜你喜欢
  • 2014-12-05
  • 2022-12-04
  • 2015-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多