2017-07-24 1 views
1

Dans une liste comme celle ci-dessous:liste Divisé en listes basées sur un caractère survenant à l'intérieur d'un élément

biglist = ['X', '1498393178', '1|Y', '15496686585007', '-82', '-80', '-80', '3', '3', '2', '|Y', '145292534176372', '-87', '-85', '-85', '3', '3', '2', '|Y', '11098646289856', '-91', '-88', '-89', '3', '3', '2', '|Y', '35521515162112', '-82', '-74', '-79', '3', '3', '2', '|Z', '0.0', '0.0', '0', '0', '0', '0', '0', '4', '0', '154'] 

Il pourrait y avoir des éléments numériques précédés d'un caractère. Je voudrais briser ce en sous-listes comme ci-dessous:

smallerlist = [ 
['X', '1498393', '1'], 
['Y', '1549668', '-82', '-80', '-80', '3', '3', '2', ''], 
['Y', '1452925', '-87', '-85', '-85', '3', '3', '2', ''], 
['Y', '3552151', '-82', '-74', '-79', '3', '3', '2', ''], 
['Z', '0.0', '0.0', '0', '0', '0', '0', '0', '4', '0', '154'] 
] 

Comme vous pouvez le dire, selon le caractère, les listes pourraient ressembler. Sinon, ils pourraient avoir un nombre différent d'éléments ou d'éléments dissemblables. Le séparateur principal est le caractère "|". J'ai essayé d'exécuter le code suivant pour diviser la liste, mais tout ce que je reçois est la même liste, plus grande, dans une liste. À savoir, la liste des len(list) == 1

import itertools 

delim = '|' 
smallerlist = [list(y) for x, y in itertools.groupby(biglist, lambda z: z == delim) if not x] 

Toute idée comment le diviser avec succès?

Répondre

6

Tout d'abord, un rapide oneliner, ce qui est une solution optimale en termes de besoins d'espace, mais il est court et doux:

>>> smallerlist = [l.split(',') for l in ','.join(biglist).split('|')] 
>>> smallerlist 
[['X', '1498393178', '1'], 
['Y', '15496686585007', '-82', '-80', '-80', '3', '3', '2', ''], 
['Y', '145292534176372', '-87', '-85', '-85', '3', '3', '2', ''], 
['Y', '11098646289856', '-91', '-88', '-89', '3', '3', '2', ''], 
['Y', '35521515162112', '-82', '-74', '-79', '3', '3', '2', ''], 
['Z', '0.0', '0.0', '0', '0', '0', '0', '0', '4', '0', '154']] 

nous rejoindre ici tous les éléments de la grande liste par un non unique, séparateur -appearing, par exemple ,, puis divisé par |, puis diviser à nouveau chaque liste dans une sous-liste des éléments d'origine.

Mais si vous cherchez un peu plus solution efficace, vous pouvez le faire avec itertools.groupby qui fonctionnera sur une liste intermédiaire, générée à la volée avec le générateur breakby(), dans lequel les éléments sans | séparateur sont renvoyés sous forme est, et ceux avec séparateur sont divisés en 3 éléments: première partie, un délimiteur de liste (par exemple None), et la deuxième partie.

from itertools import groupby 

def breakby(biglist, sep, delim=None): 
    for item in biglist: 
     p = item.split(sep) 
     yield p[0] 
     if len(p) > 1: 
      yield delim 
      yield p[1] 

smallerlist = [list(g) for k,g in groupby(breakby(biglist, '|', None), 
              lambda x: x is not None) if k] 
2

Il serait plus facile de joindre les éléments de la liste en une seule chaîne, diviser la chaîne sur le caractère '|', puis diviser chacun de ces éléments sur la ce que vous utilisé pour joindre la liste. Probablement une virgule ,

bigstr = ','.join(biglist) 

[line.split(',') for line in bigstr.split('|')] 

# returns 
[['X', '1498393178', '1'], 
['Y', '15496686585007', '-82', '-80', '-80', '3', '3', '2', ''], 
['Y', '145292534176372', '-87', '-85', '-85', '3', '3', '2', ''], 
['Y', '11098646289856', '-91', '-88', '-89', '3', '3', '2', ''], 
['Y', '35521515162112', '-82', '-74', '-79', '3', '3', '2', ''], 
['Z', '0.0', '0.0', '0', '0', '0', '0', '0', '4', '0', '154']] 

Si la liste est très longue, vous pouvez aussi parcourir les éléments de la liste, la création d'une nouvelle sous-listes lorsque vous rencontrez un caractère pipe |

new_biglist = [] 
sub_list = [] 
for item in biglist: 
    if '|' in item: 
     end, start = item.split('|') 
     sub_list.append(end) 
     new_biglist.append(sub_list) 
     sub_list = [start] 
    else: 
     sub_list.append(item) 

new_biglist 
# return: 
[['X', '1498393178', '1'], 
['Y', '15496686585007', '-82', '-80', '-80', '3', '3', '2', ''], 
['Y', '145292534176372', '-87', '-85', '-85', '3', '3', '2', ''], 
['Y', '11098646289856', '-91', '-88', '-89', '3', '3', '2', ''], 
['Y', '35521515162112', '-82', '-74', '-79', '3', '3', '2', '']] 
+0

C'est une très bonne solution aussi, j'ai essayé et ça marche. Pour votre partie éditée, cela déclenche un 'NameError' pour' start' – omrakhur

0

Vous n « t besoin regex ou quelque chose du genre - une boucle simple et str.split() devrait être plus que suffisant, au moins si vous êtes après une solution efficace réelle:

biglist = ['X', '1498393178', '1|Y', '15496686585007', '-82', '-80', '-80', '3', '3', '2', 
      '|Y', '145292534176372', '-87', '-85', '-85', '3', '3', '2', '|Y', 
      '11098646289856', '-91', '-88', '-89', '3', '3', '2', '|Y', '35521515162112', 
      '-82', '-74', '-79', '3', '3', '2', '|Z', '0.0', '0.0', '0', '0', '0', '0', 
      '0', '4', '0', '154'] 

delimiter = "|" 
smaller_list = [[]] 
for x in biglist: 
    if delimiter in x: 
     a, b = x.split(delimiter) 
     if a: # remove the check if you also want the empty elements 
      smaller_list[-1].append(a) 
     smaller_list.append([]) 
     if b: # remove the check if you also want the empty elements 
      smaller_list[-1].append(b) 
    else: 
     smaller_list[-1].append(x) 

print(smaller_list) 
# [['X', '1498393178', '1'], 
# ['Y', '15496686585007', '-82', '-80', '-80', '3', '3', '2'], 
# ['Y', '145292534176372', '-87', '-85', '-85', '3', '3', '2'], 
# ['Y', '11098646289856', '-91', '-88', '-89', '3', '3', '2'], 
# ['Y', '35521515162112', '-82', '-74', '-79', '3', '3', '2'], 
# ['Z', '0.0', '0.0', '0', '0', '0', '0', '0', '4', '0', '154']]