web-dev-qa-db-fra.com

Python trouve des nombres entre les plages d'une liste ou d'un tableau

J'ai une liste avec des millions de numéros qui augmentent constamment jusqu'à la fin. Je dois trouver et renvoyer des nombres dans une plage spécifiée, par exemple. nombres supérieurs à X mais inférieurs à Y, les nombres de la liste peuvent changer et les valeurs que je recherche changent également

J'utilise cette méthode. Veuillez noter qu'il s'agit d'un exemple élémentaire. Les chiffres ne sont ni uniformes ni identiques à ceux indiqués ci-dessous dans mon programme.

l = [i for i in range(2000000)]
nums = []
for element in l:
    if element > 950004:
        break
    if element > 950000:
        nums.append(element)
#[950001, 950002, 950003, 950004]

Bien que rapide, j'ai besoin que ce soit un peu plus rapide pour ce que mon programme fait, les chiffres changent beaucoup alors je me demande s'il y a une meilleure façon de faire cela avec une série de pandas ou un tableau numpy? mais jusqu'ici tout ce que j'ai fait est de faire un exemple en numpy:

a = numpy.array(l,dtype=numpy.int64)

Une série de pandas serait-elle plus fonctionnelle? Utilisation de query ()? Quelle serait la meilleure façon d'aborder cela avec un tableau plutôt qu'une liste d'objets python python

6
citizen2077

Voici une solution utilisant la recherche binaire. Vous parlez de millions de chiffres. La recherche techniquement binaire accélérera l'algorithme en réduisant la complexité d'exécution à O (log n) en négligeant l'étape de découpage finale.

import bisect

l = [i for i in range(2000000)]
lower_bound = 950000
upper_bound = 950004

lower_bound_i = bisect.bisect_left(l, lower_bound)
upper_bound_i = bisect.bisect_right(l, upper_bound, lo=lower_bound_i)
nums = l[lower_bound_i:upper_bound_i]
9
Calculator

Voici deux implémentations pour la recherche binaire (basée sur le code de ici ) - une recherche une limite supérieure et une recherche une limite inférieure. Est-ce que cela fonctionne mieux pour vous? 

def binary_search_upper(seq, limit):
    min = 0
    max = len(seq) - 1
    while True:
        if max < min:
            return -1
        m = (min + max) / 2
        if m == (len(seq) -1) or (seq[m] <= limit and seq[m+1] > limit):
            return m
        Elif seq[m] < limit:
            min = m+1
        else:
            max = m - 1

def binary_search_lower(seq, limit):
    min = 0
    max = len(seq) - 1
    while True:
        if max < min:
            return -1
        m = (min + max) / 2
        if m == 0 or (seq[m] >= limit and seq[m-1] < limit):
            return m
        Elif seq[m] < limit:
            min = m+1
        else:
            max = m - 1


l = [i for i in range(2000000)]
print binary_search_upper(l, 950004)
print binary_search_lower(l, 950000)
2
Maor Veitsman

Vous pouvez utiliser numpy pour obtenir un sous-ensemble de votre liste en utilisant une tranche booléenne.

import numpy as np
a = np.arange(2000000)
nums = a[(950000<a) & (a<=950004)]
nums
# returns
array([950001, 950002, 950003, 950004])
0
James