web-dev-qa-db-fra.com

Scinder la liste en listes en fonction d'un caractère apparaissant à l'intérieur d'un élément

Dans une liste comme celle ci-dessous:

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 diviser cela 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 constater, les listes peuvent ressembler, selon le personnage. Sinon, ils pourraient avoir un nombre différent d’éléments, ou même des éléments dissemblables. Le séparateur principal est le caractère "|". J'ai essayé d'exécuter le code suivant pour scinder la liste, mais tout ce que j'obtiens est la même, plus grande, dans une liste. I.e., liste de len(list) == 1.

import itertools

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

Des idées comment diviser avec succès?

3
omrakhur

Tout d’abord, un rapide oneliner , qui n’est pas une solution optimale en termes d’encombrement, mais qui est court et simple:

>>> 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']]

Ici, nous joignons tous les éléments de la grande liste par un séparateur unique n'apparaissant pas, par exemple ,, puis divisé par |, puis scindé à nouveau chaque liste en 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 laquelle les éléments sans | separator sont retournés tels quels, et ceux avec separator sont divisés en 3 éléments: la première partie, un séparateur de liste (par exemple, None), et la seconde 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]
7
randomir

Il serait plus facile de joindre les éléments de la liste en une seule chaîne, de scinder la chaîne sur le caractère '|', puis de diviser chacun de ces éléments sur l'élément que vous avez utilisé pour rejoindre 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 également parcourir les éléments de la liste et créer une nouvelle sous-liste lorsque vous rencontrez un caractère de 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', '']]
2
James

Voici une solution à un problème similaire auquel je n’ai pas trouvé de réponse. Comment diviser une liste en sous-listes délimitées par un membre, par ex. personnage:

l = ['r', 'g', 'b', ':',
     'D', 'E', 'A', 'D', '/',
     'B', 'E', 'E', 'F', '/',
     'C', 'A', 'F', 'E']

def split_list(thelist, delimiters):
    ''' Split a list into sub lists, depending on a delimiter.

        delimiters - item or Tuple of item
    '''
    results = []
    sublist = []

    for item in thelist:
        if item in delimiters:
            results.append(sublist) # old one
            sublist = []            # new one
        else:
            sublist.append(item)

    if sublist:  # last bit
        results.append(sublist)

    return results


print(
    split_list(l, (':', '/'))
)
# => [['r', 'g', 'b'], ['D', 'E', 'A', 'D'], 
#     ['B', 'E', 'E', 'F'], 
#     ['C', 'A', 'F', 'E']]
0
Gringo Suave

Vous n'avez pas besoin de regex ou quoi que ce soit du genre - une simple boucle et str.split() devrait suffire amplement, du moins si vous recherchez une solution efficace:

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']]
0
zwer