2014-07-22 43 views
6

Tôi có mảng sauTìm các số không liên tiếp trong một mảng NumPy

a = [1, 2, 3, 0, 0, 0, 0, 0, 0, 4, 5, 6, 0, 0, 0, 0, 9, 8, 7,0,10,11] 

Những gì tôi muốn tìm điểm bắt đầu và chỉ số cuối của mảng nơi các giá trị là số không liên tục, đối với các mảng trên đầu ra trông giống như sau

[3,8],[12,15],[19] 

Tôi muốn làm điều đó càng hiệu quả càng tốt.

+0

Tại sao bỏ phiếu, Xin hãy viết lại hồ sơ – Shan

+2

Không phải tôi, nhưng nó là truyền thống để nói điều gì đó như "Tôi có mã này" (và hiển thị nó) và nó không hoạt động. Bạn đã không hiển thị những gì bạn đã thử. – doctorlove

+0

tốt, tôi chỉ có thể đi qua mảng với một vòng lặp và đánh dấu các chỉ số bắt đầu và kết thúc, tôi nghĩ rằng những người biết python sẽ hiểu nó dễ dàng – Shan

Trả lời

11

Dưới đây là một việc thực hiện vectorized khá nhỏ gọn. Tôi đã thay đổi các yêu cầu một chút, vì vậy giá trị trả về là "bit" một chút: nó tạo ra một mảng có hình dạng (m, 2), trong đó m là số "chạy" của số không. Cột đầu tiên là chỉ số của 0 đầu tiên trong mỗi lần chạy và cột thứ hai là chỉ mục của phần tử nonzero đầu tiên sau khi chạy. (Mô hình lập chỉ mục này phù hợp, ví dụ, làm thế nào cắt công trình và làm thế nào range chức năng hoạt động.)

import numpy as np 

def zero_runs(a): 
    # Create an array that is 1 where a is 0, and pad each end with an extra 0. 
    iszero = np.concatenate(([0], np.equal(a, 0).view(np.int8), [0])) 
    absdiff = np.abs(np.diff(iszero)) 
    # Runs start and end where absdiff is 1. 
    ranges = np.where(absdiff == 1)[0].reshape(-1, 2) 
    return ranges 

Ví dụ:

In [236]: a = [1, 2, 3, 0, 0, 0, 0, 0, 0, 4, 5, 6, 0, 0, 0, 0, 9, 8, 7, 0, 10, 11] 

In [237]: runs = zero_runs(a) 

In [238]: runs 
Out[238]: 
array([[ 3, 9], 
     [12, 16], 
     [19, 20]]) 

Với định dạng này, nó rất đơn giản để có được số lượng các zeros trong mỗi lần chạy:

In [239]: runs[:,1] - runs[:,0] 
Out[239]: array([6, 4, 1]) 

Nó luôn luôn là một ý tưởng tốt để kiểm tra các trường hợp cạnh:

In [240]: zero_runs([0,1,2]) 
Out[240]: array([[0, 1]]) 

In [241]: zero_runs([1,2,0]) 
Out[241]: array([[2, 3]]) 

In [242]: zero_runs([1,2,3]) 
Out[242]: array([], shape=(0, 2), dtype=int64) 

In [243]: zero_runs([0,0,0]) 
Out[243]: array([[0, 3]]) 
+0

cách nào để làm điều đó với gấu trúc? – toine

1

Bạn có thể sử dụng itertools để đạt được kết quả mong đợi.

from itertools import groupby 
a= [1, 2, 3, 0, 0, 0, 0, 0, 0, 4, 5, 6, 0, 0, 0, 0, 9, 8, 7,0,10,11] 
b = range(len(a)) 
for group in groupby(iter(b), lambda x: a[x]): 
    if group[0]==0: 
     lis=list(group[1]) 
     print [min(lis),max(lis)] 
+0

Điều này sẽ trả về '[19, 19]', tôi nghĩ OP mong đợi chỉ [19]. Và thay vì tạo danh sách không cần thiết 'b', hãy thử sử dụng' liệt kê (a). ' –

0

Đây là một chức năng tùy chỉnh, không chắc chắn hiệu quả nhất nhưng hoạt động:

def getZeroIndexes(li): 
    begin = 0 
    end = 0 
    indexes = [] 
    zero = False 
    for ind,elt in enumerate(li): 
    if not elt and not zero: 
     begin = ind 
     zero = True 
    if not elt and zero: 
     end = ind 
    if elt and zero: 
     zero = False 
     if begin == end: 
     indexes.append(begin) 
     else: 
     indexes.append((begin, end)) 

    return indexes 
Các vấn đề liên quan