2
votes

Comment diviser les éléments consécutifs d'une liste en sous-listes

J'ai la liste suivante:

indices_to_remove_1 : [0,1,2,3,....,600]
indices_to_remove_2 : [800,801,802,....,1200]
indices_to_remove_3 : [1600,1601,1602,....., 1800]

J'ai essentiellement 3 sous-ensembles d'indices consécutifs:

  1. 0-600
  2. 800-1200
  3. 1600-1800

Je voudrais créer 3 petites listes différentes qui n'incluront que des nombres consécutifs.

Résultat attendu:

indices_to_remove: [0,1,2,3,..,600,800,801,802,....,1200,1600,1601,1602,...,1800]

P.S: Les nombres sont arbitraires et aléatoires; de plus, je peux rencontrer plus de 3 sous-ensembles ou moins.


2 commentaires

Vous souhaitez diviser les listes sur les lacunes?


Ouais en gros. Le plus important est de diviser les indices consécutifs dans une sous-liste @StephenRauch


3 Réponses :


3
votes

J'aime utiliser des générateurs pour ce genre de problème. Vous pouvez procéder comme suit:

Diviser les données non consécutives:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90]
[160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170]

Code de test:

indices_to_remove = (
        list(range(0, 11)) +
        list(range(80, 91)) +
        list(range(160, 171))
)

for i in split_non_consequtive(indices_to_remove):
    print(i)

Résultats:

def split_non_consequtive(data):
    data = iter(data)
    val = next(data)
    chunk = []
    try:
        while True:
            chunk.append(val)
            val = next(data)
            if val != chunk[-1] + 1:
                yield chunk
                chunk = []
    except StopIteration:
        if chunk:
            yield chunk


5 commentaires

Notez que vous pouvez utiliser itertools.groupby ici ... C'est un peu difficile à faire mais une astuce assez intéressante: [[el [1] for el in g] for k, g in itertools.groupby (enumerate (indices_to_remove), lambda L: L [1] - L [0])] : p


@JonClements, très bien!


Merci @StephenRauch. Cependant, existe-t-il un moyen possible de modifier le code pour supprimer les trois premier et dernier éléments de chaque sous-liste produite?


print (i [3: -3]) ou yield chunk [3: -3]


@Stephen Je me souviens vaguement qu'il s'agissait d'un exemple de recette itertools dans la documentation Python 2.5 ou quelque chose comme ça, mais je ne l'ai pas vu depuis ... Je pensais juste que vous pourriez l'apprécier :)



1
votes

Une autre méthode consiste à utiliser more_itertools.consecutive_groups : ( a utilisé la liste de @ Stephen comme exemple ):

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90]
[160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170]

import more_itertools as mit
for group in mit.consecutive_groups(indices_to_remove):
    print(list(group))


5 commentaires

Merci, @ anky_91 pour votre réponse, mais j'aimerais savoir s'il serait possible d'éliminer les deux premier et dernier éléments de toutes les sous-listes que nous avons créées.


Merci encore. @ anky_91 Une dernière question: je voudrais savoir s'il existe un moyen de combiner toutes les sous-listes créées dans une grande liste, mon objectif principal était de diviser la liste en sous-listes et de supprimer les 5 premier et dernier éléments, et après cela pour combinez-les dans une liste. Merci encore


@AlexDavies vous voulez dire [list (group) [2: -2] for group in mit.consecutive_groups (index_to_remove)] ??


@ andy_91, oui, c'est ce que je voulais dire. le seul problème en l'utilisant est que cela créera plusieurs sous-listes dans une grande liste. Par exemple: list = [[liste 1], [liste 2], [liste 3]] et j'aimerais avoir une grande liste sans minilistes à l'intérieur.


@AlexDavies list (itertools.chain.from_iterable ([list (group) [2: -2] for group in mit.consecutive_groups (index_to_remove)])) , import itertools première



0
votes

Sans compliquer les choses, vous pouvez simplement résoudre quelque chose comme ceci:

[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90], [160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170]]

Test:

#Stephen's list 
print(list(chunk_lists_(list(range(0, 11)) +
        list(range(80, 91)) +
        list(range(160, 171)))))

sortie:

def chunk_lists_(data_):

    consecutive_list = []

    for chunks in range(len(data_)):

        try:

            #check consecutiveness
            if data_[chunks + 1] - data_[chunks] == 1:

                #check if it's already in list
                if data_[chunks] not in consecutive_list:
                    consecutive_list.append(data_[chunks])

                #add last one too
                consecutive_list.append(data_[chunks + 1])

            else:

                #yield here and empty list
                yield consecutive_list
                consecutive_list = []
        except Exception:
            pass
    yield consecutive_list


0 commentaires