Python >> Tutoriel Python >  >> Python Tag >> NumPy

Existe-t-il un moyen pythonique d'échantillonner N éléments consécutifs à partir d'une liste ou d'un tableau numpy

Utilisez itertools , en particulier islice et cycle .

start = random.randint(0, len(Choice) - 1)
list(islice(cycle(Choice), start, start + n))

cycle(Choice) est une séquence infinie qui répète votre liste d'origine, de sorte que la tranche start:start + n enveloppera si nécessaire.


Vous pouvez utiliser une compréhension de liste, en utilisant des opérations modulo sur l'index pour le maintenir dans la plage de la liste :

Choice = [1,2,3,4,5,6] 
X = 4 
N = 4
L = len(Choice)
Selection = [Choice[i % L] for i in range(X, X+N)]
print(Selection)

Sortie

[5, 6, 1, 2]

Notez que si N est inférieur ou égal à len(Choice) , vous pouvez grandement simplifier le code :

Choice = [1,2,3,4,5,6] 
X = 4 
N = 4
L = len(Choice)
Selection = Choice[X:X+N] if X+N <= L else Choice[X:] + Choice[:X+N-L]
print(Selection)

Puisque vous demandez le moyen le plus efficace, j'ai créé un petit benchmark pour tester les solutions proposées dans ce fil.

J'ai réécrit votre solution actuelle comme :

def op(choice, x):
    n = len(choice)
    selection = []
    for i in range(x, x + n):
        selection.append(choice[i % n])
    return selection

choice est la liste d'entrée et x est l'index aléatoire.

Ce sont les résultats si choice contient 1_000_000 nombres aléatoires :

chepner: 0.10840400000000017 s
nick: 0.2066781999999998 s
op: 0.25887470000000024 s
fountainhead: 0.3679908000000003 s

Code complet

import random
from itertools import cycle, islice
from time import perf_counter as pc
import numpy as np


def op(choice, x):
    n = len(choice)
    selection = []
    for i in range(x, x + n):
        selection.append(choice[i % n])
    return selection


def nick(choice, x):
    n = len(choice)
    return [choice[i % n] for i in range(x, x + n)]


def fountainhead(choice, x):
    n = len(choice)
    return np.take(choice, range(x, x + n), mode='wrap')


def chepner(choice, x):
    n = len(choice)
    return list(islice(cycle(choice), x, x + n))


results = []
n = 1_000_000
choice = random.sample(range(n), n)
x = random.randint(0, n - 1)

# Correctness
assert op(choice, x) == nick(choice,x) == chepner(choice,x) == list(fountainhead(choice,x))

# Benchmark
for f in op, nick, chepner, fountainhead:
    t0 = pc()
    f(choice, x)
    t1 = pc()
    results.append((t1 - t0, f))

for t, f in sorted(results):
    print(f'{f.__name__}: {t} s')