2017-08-28 107 views
5

ile numaralarının listesini değiştirin:düz alt aralıkları böyle numarası listesi göz önüne alındığında

lst = [0, 10, 15, 17] 

ben lst tüm i için i -> i + 3 öğeleri olan bir liste istiyorum. Eğer örtüşen aralıklar varsa, onları birleştirmeyi isterim.

[0, 1, 2, 3,  10, 11, 12, 13,  15, 16, 17, 18, 17, 18, 19, 20] 

Fakat son 2 grup için, aralıkları onları birleştirme üzerine böylece şunlara sahip, üst üste:

Yani, yukarıdaki örneğin, öncelikle olsun

[0, 1, 2, 3,  10, 11, 12, 13,  15, 16, 17, 18,  19, 20] 

budur istediğim çıktı. (10000 loops, best of 3: 56 µs per loop)

from collections import OrderedDict 

res = list(OrderedDict.fromkeys([y for x in lst for y in range(x, x + 4)]).keys()) 
print(res) = [0, 1, 2, 3, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20] 

Ancak bu yavaş:

Bu hep düşünmüşümdür şeydir. Mümkünse uyuşmuş bir çözüm ya da bundan daha hızlı bir python çözümü istiyorum.

+0

, sınıflandırılması garanti edilen orijinal öğeler nelerdir? –

+0

@ Ev.Kounis Evet. Garantili. –

+0

@ Coldspeed daha sonra bunu kullanabilirsiniz. 'Set' için döküm ve daha hızlı hale getirirse tekrar 'sort'ing. –

cevap

6

Yaklaşım # 1: benzersiz sayılarını almak için broadcasted toplamı ve sonra np.unique kullanarak dayalı Bir yaklaşım -

np.unique(np.asarray(lst)[:,None] + np.arange(4)) 

Yaklaşım # 2: Başka yayınlanan toplamı esas ve sonra maskeleme -

def mask_app(lst, interval_len = 4): 
    arr = np.array(lst) 
    r = np.arange(interval_len) 
    ranged_vals = arr[:,None] + r 
    a_diff = arr[1:] - arr[:-1] 
    valid_mask = np.vstack((a_diff[:,None] > r, np.ones(interval_len,dtype=bool))) 
    return ranged_vals[valid_mask] 

Çalışma zamanı sınaması

Orjinal yaklaşım -

from collections import OrderedDict 
def org_app(lst): 
    list(OrderedDict.fromkeys([y for x in lst for y in range(x, x + 4)]).keys()) 

Zamanlamaları - o kadar da iyi sonradan amorti gibi görünüyor olsa da, array dönüşüm ile benzeri

In [409]: n = 10000 

In [410]: lst = np.unique(np.random.randint(0,4*n,(n))).tolist() 

In [411]: %timeit org_app(lst) 
    ...: %timeit np.unique(np.asarray(lst)[:,None] + np.arange(4)) 
    ...: %timeit mask_app(lst, interval_len = 4) 
    ...: 
10 loops, best of 3: 32.7 ms per loop 
1000 loops, best of 3: 1.03 ms per loop 
1000 loops, best of 3: 671 µs per loop 

In [412]: n = 100000 

In [413]: lst = np.unique(np.random.randint(0,4*n,(n))).tolist() 

In [414]: %timeit org_app(lst) 
    ...: %timeit np.unique(np.asarray(lst)[:,None] + np.arange(4)) 
    ...: %timeit mask_app(lst, interval_len = 4) 
    ...: 
1 loop, best of 3: 350 ms per loop 
100 loops, best of 3: 14.7 ms per loop 
100 loops, best of 3: 9.73 ms per loop 

iki yayınlanan yaklaşımlarıyla darboğaz gibi görünüyor. Sadece son veri kümesi dönüşüm için harcanan zaman duygusu vermek için -

In [415]: %timeit np.array(lst) 
100 loops, best of 3: 5.6 ms per loop 
+0

Güzel. Bir çekicilik ve yanan bir hızlı gibi çalışır. –