J'essaie d'accomplir la tâche suivante et j'échoue jusqu'à présent. J'ai deux listes triées de nombres. Dites
[[*a, b] for b, a in itertools.groupby(A, lambda x: next(filter(lambda y: y >= x, B)))]
Je veux faire une liste de listes. Chaque liste contient une valeur différente de B et toutes les valeurs de A entre cette valeur B et celle qui la précède directement dans la liste. La première liste contient juste tout ce qui est plus petit que la première valeur de B.
Dans ce cas, la liste des listes devrait commencer
[[5.8, 6.5, 7.6, 9.0], [13.5], [14.5, 18.1, 22.5], [25.7, 26.4, 30.7. 30.9, 32.3]....]
Je serais heureux avec du code numpy si c'est plus simple / plus rapide.
J'ai essayé:
A = [5.8, 6.5, 7.6, 14.5, 18.1, 25.7, 26.4, 30.7, 30.9, 33.6, 38.6, 38.8, 39.2] B = [9.0, 13.5, 22.5, 32.3 40.6, 43.2, 47.9, 54.2, 60.3, 63.0]
mais il manque toutes les listes de singleton et je ne sais pas à quelle vitesse c'est en tout cas.
5 Réponses :
vous pouvez faire,
result = [*map(lambda x : list(x), result),] print(result) # [[5.8, 6.5, 7.6, 9.0], [13.5], [14.5, 18.1, 22.5], [25.7, 26.4, 30.7, 30.9, # 32.3], [33.6, 38.6, 38.8, 39.2, 40.6], [43.2], [47.9], [54.2], [60.3], [63.0]]
et si vous ne voulez que des listes, vous pouvez faire ensuite:
import numpy as np A = [5.8, 6.5, 7.6, 14.5, 18.1, 25.7, 26.4, 30.7, 30.9, 33.6, 38.6, 38.8, 39.2] B = [9.0, 13.5, 22.5, 32.3, 40.6, 43.2, 47.9, 54.2, 60.3, 63.0] A = np.array(A) B = np.hstack(([-np.inf], B)) result = [np.r_[np.extract((A>B[i]) & (A<= B[i+1]), A), B[i+1]] for i in range(len(B)-1)]
Cela crée beaucoup de tableaux vides. [tableau ([], dtype = float64), tableau ([5.8, 6.5, 7.6]), tableau ([], dtype = float64), etc.
Il ne devrait pas y avoir de listes vides. La réponse devrait ressembler à [[5.8, 6.5, 7.6, 9.0], [13.5], [14.5, 18.1, 22.5], [25.7, 26.4, 30.7. 30,9, 32,3] ...]
Votre réponse comporte deux lignes result . Le premier donne: [tableau ([- inf]), tableau ([- inf]), tableau ([5.8, 6.5, 7.6, 9.]), tableau ([13.5]), etc.
Cela fonctionne très bien, peut-être que vous ne l'avez pas copié correctement
Ah oui! Merci.
heureux d'avoir pu aider
J'utiliserais deux pointeurs comme celui-ci,
i = 0
j= 0
ans = [] #contains the lists of lists
while j<len(B):
to_append = []
while i<len(A) and A[i]<=B[j]:
to_append.append(A[i])
i=i+1
to_append.append(B[j])
ans.append(to_append)
j=j+1
Essayez maintenant
Au moins pour cet exemple, cette approche de liste est beaucoup plus rapide que celles de numpy .
Cela fonctionnera un peu plus rapidement en utilisant for b in B à la place de l'itération j . J'ai également essayé de remplacer l'itération i par un itérateur sur iter (A) ou un générateur, mais jusqu'à présent sans succès.
C'est juste de la logique vanille. Je suis sûr que nous pouvons également le vectoriser. Je vais essayer et ajouter une modification plus tard dans la journée
C'est très joli et propre.
En tant qu'approche purement basée sur Numpy (pas si significative que cela), vous pouvez convertir vos listes en tableau et faire ce qui suit:
In [43]: ind = (b[:,None] > a).sum(1) In [44]: np.split(np.insert(a, ind, b), ind + np.arange(1, ind.size +1)) Out[44]: [array([5.8, 6.5, 7.6, 9. ]), array([13.5]), array([14.5, 18.1, 22.5]), array([25.7, 26.4, 30.7, 30.9, 32.3]), array([33.6, 38.6, 38.8, 39.2, 40.6]), array([43.2]), array([47.9]), array([54.2]), array([60.3]), array([63.]), array([], dtype=float64)]
Utilisez np.searchsorted pour résoudre le problème en temps O (N * logN). Tout d'abord, trouvez la position des éléments de B dans A. Ensuite, divisez le tableau A en utilisant ces positions. Enfin, créez une liste des propriétés souhaitées.
res_list = list(map(np.ndarray.tolist, res))
Cela générera la liste requise de ndarrays que vous pourrez reconvertir en liste en utilisant la méthode ndarray.tolist ():
pos = np.searchsorted(A,B) chunks = np.split(A, pos) res = [np.hstack(ab) for ab in zip(chunks,B)]
Vous pouvez utiliser heapq.merge pour une solution O (n + m):
from itertools import chain, repeat from heapq import merge [*map(list, map(chain, map(iter, repeat(merge(A,B).__next__), B), zip(B)))] # [[5.8, 6.5, 7.6, 9.0], [13.5], [14.5, 18.1, 22.5], [25.7, 26.4, 30.7, 30.9, 32.3], [33.6, 38.6, 38.8, 39.2, 40.6], [43.2], [47.9], [54.2], [60.3], [63.0]]
Cela utilise merge pour fusionner A et B dans l'ordre. Ensuite, la forme à deux arguments de iter est utilisée pour séparer les éléments de B. Cela mange malheureusement les points de partage, donc nous les rattacheons en utilisant itertools.chain.
C'est très gentil.
Qu'est-ce que tu as essayé jusque-là?
Étant donné que les listes résultantes varient en longueur, cela ne convient pas avec
numpy. Utilisez simplement les opérations de liste. Ne vous inquiétez pas de la vitesse à ce stade. Pour commencer, je voudrais juste itérer surb, en collectant les valeurs pertinentes dea. N'essayez rien d'extraordinaire.Cela ne semble pas facile à "vectoriser", c'est à cela que sert généralement
numpy. En fait, toutes vos listes seront irrégulières, c'est donc un autre problème. Si vous voulez vraiment que cela fonctionne dans numpy, pensez à écrire une extension C.