Python creates tuple groups in a list from another list

Let's say I have this data:

data = [1, 2, 3, -4, -5, 3, 2, 4, -2, 5, 6, -5, -1, 1]

I need it to be grouped into another list by tuples. One tuple consists of two lists. One for positive numbers, the other for negative. And tuples must be created by checking what number it is. The last negative number (I mean that there were no positive numbers between the negative numbers) means that the other numbers must go to another tuple, and when it finds another last negative number, it must create another tuple.

Thus, the rules are as follows: all the numbers found are added to the first tuple, when he finds a negative number, he still adds it to this tuple until he finds a positive number (this means that you need to create a new tuple).

I think it’s easier to show than to explain. After parsing, the datalist should look like this:

l = [([1, 2, 3], [-4, -5]), ([3, 2, 4], [-2]), ([5, 6], [-5, -1]), ([1], [])]

I created a solution, but I wonder if it is enough. Perhaps you can write more elegant (and I'm wondering about performance, is there a better way to write such a parser with the best performance :))?

def neighborhood(iterable):
    iterator = iter(iterable)
    prev = None
    item = iterator.next()  # throws StopIteration if empty.
    for next in iterator:
        yield (prev,item,next)
        prev = item
        item = next
    yield (prev,item,None)

l = []    
pos = []
neg = []
for prev, item, next in neighborhood(data):
    if item > 0:
        pos.append(item)
        if not next:
            l.append((pos, neg))
    else:
        neg.append(item)
        if next > 0:
            l.append((pos, neg))
            pos = []
            neg = []
        elif not next:
            l.append((pos, neg))

print l

PS if not nextpart, I think, can be used only once after the main check.

+4
source share
2 answers

itertools.groupby, , / , , , :

from itertools import groupby, zip_longest

x = (list(v) for k,v in groupby(data, lambda x: x < 0))
l = list(zip_longest(x, x, fillvalue=[]))

l :

[([1, 2, 3], [-4, -5]), ([3, 2, 4], [-2]), ([5, 6], [-5, -1]), ([1], [])]

:

  • / groupby, ( ).

  • zipping-a-generator Python. , zip , .

  • Python 2 izip_longest.

+8

O(n), , @ajcr, .

def pos_neg(data):
  split = []
  for r in data:
    if len(split) == 0 or (r > 0 and len(split[-1][-1]) > 0):
      split.append(([], []))

    if r < 0:
      split[-1][-1].append(r)
    else:
      split[-1][-2].append(r)

  return split

data = [1, 2, 3, -4, -5, 3, 2, 4, -2, 5, 6, -5, -1, 1]
print pos_neg(data)
#=> [([1, 2, 3], [-4, -5]), ([3, 2, 4], [-2]), ([5, 6], [-5, -1]), ([1], [])]
0

Source: https://habr.com/ru/post/1616609/


All Articles