Nhận các chỉ số của giá trị True trong danh sách boolean


87

Tôi có một đoạn mã để tạo tổng đài. Tôi muốn trả lại danh sách tất cả các công tắc đang bật. Ở đây "on" sẽ bằng nhau Truevà "off" bằng nhau False. Vì vậy, bây giờ tôi chỉ muốn trả về một danh sách tất cả các Truegiá trị và vị trí của chúng. Đây là tất cả những gì tôi có nhưng nó chỉ trả về vị trí của lần xuất hiện đầu tiên True(đây chỉ là một phần mã của tôi):

self.states = [False, False, False, False, True, True, False, True, False, False, False, False, False, False, False, False]

def which_switch(self):
    x = [self.states.index(i) for i in self.states if i == True]

Điều này chỉ trả về "4"

Câu trả lời:


116

Sử dụng enumerate, list.indextrả về chỉ mục của kết quả phù hợp đầu tiên được tìm thấy.

>>> t = [False, False, False, False, True, True, False, True, False, False, False, False, False, False, False, False]
>>> [i for i, x in enumerate(t) if x]
[4, 5, 7]

Đối với các danh sách lớn, tốt hơn nên sử dụng itertools.compress:

>>> from itertools import compress
>>> list(compress(xrange(len(t)), t))
[4, 5, 7]
>>> t = t*1000
>>> %timeit [i for i, x in enumerate(t) if x]
100 loops, best of 3: 2.55 ms per loop
>>> %timeit list(compress(xrange(len(t)), t))
1000 loops, best of 3: 696 µs per loop

À, tôi hiểu rồi, tôi thấy một số câu hỏi tương tự yêu cầu tôi sử dụng kiểu liệt kê, nhưng tôi đoán là tôi đã sử dụng sai. Tôi đã đặt danh sách bằng x, sau đó làm enumerate(x)nhưng tôi đoán tất cả những gì tôi đang làm là liệt kê 4? Đó là những gì đang xảy ra? Thanks for the help
Charles Smith

Ngoài ra, điều gì đang xảy ra khi bạn làm i for i, xtrong phần hiểu danh sách? Tôi chỉ quen i for ivới ví dụ, hoặc một định dạng tương tự, chức năng của nó là xgì? Cảm ơn
Charles Smith

1
@Amon enumeratetrả về một tuples (ind, giá trị) trong vòng lặp, bây giờ chúng ta có thể gán các mục của tuple để hai biến sử dụng: i, x = (ind, value). Đây chính xác là những gì đang xảy ra trong vòng lặp đó.
Ashwini Chaudhary

Ồ, tôi thấy chuyện gì đang xảy ra bây giờ. Cảm ơn rất nhiều vì sự giúp đỡ của bạn!
Charles Smith

Đối với bất kỳ ai sử dụng Python3, trong itertools.compressgiải pháp, hãy thay đổi xrangethành range. ( xrangeđã được đổi tên thành rangebằng Python 3)
MehmedB

64

Nếu bạn có sẵn numpy:

>>> import numpy as np
>>> states = [False, False, False, False, True, True, False, True, False, False, False, False, False, False, False, False]
>>> np.where(states)[0]
array([4, 5, 7])

8
Lưu ý rằng lợi nhuận này một tuple đòi hỏi np.where(states)[0]để thực sự sử dụng kết quả
Rufus

17

TL; DR : sử dụng np.wherevì nó là lựa chọn nhanh nhất. Lựa chọn của bạn np.where, itertools.compresslist comprehension.

Xem so sánh chi tiết bên dưới, nơi nó có thể được thấy np.wheretốt hơn cả hai itertools.compressvà cũng nhưlist comprehension .

>>> from itertools import compress
>>> import numpy as np
>>> t = [False, False, False, False, True, True, False, True, False, False, False, False, False, False, False, False]`
>>> t = 1000*t
  • Phương pháp 1: Sử dụng list comprehension
>>> %timeit [i for i, x in enumerate(t) if x]
457 µs ± 1.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
  • Phương pháp 2: Sử dụng itertools.compress
>>> %timeit list(compress(range(len(t)), t))
210 µs ± 704 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
  • Phương pháp 3 (phương pháp nhanh nhất): Sử dụng numpy.where
>>> %timeit np.where(t)
179 µs ± 593 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

2

Bạn có thể sử dụng bộ lọc cho nó:

filter(lambda x: self.states[x], range(len(self.states)))

Các rangeđây liệt kê các yếu tố của danh sách của bạn và kể từ khi chúng tôi muốn chỉ những nơi self.statesđược True, chúng tôi đang áp dụng một bộ lọc dựa trên tình trạng này.

Đối với Python> 3.0:

list(filter(lambda x: self.states[x], range(len(self.states))))


1

Sử dụng cách hiểu từ điển,

x = {k:v for k,v in enumerate(states) if v == True}

Đầu vào:

states = [False, False, False, False, True, True, False, True, False, False, False, False, False, False, False, False]

Đầu ra:

{4: True, 5: True, 7: True}

3
Đó là một sự đọc hiểu chính tả không phải là sự hiểu biết danh sách.
Ashwini Chaudhary

1

Sử dụng phép nhân khôn ngoan nguyên tố và một tập hợp:

>>> states = [False, False, False, False, True, True, False, True, False, False, False, False, False, False, False, False]
>>> set(multiply(states,range(1,len(states)+1))-1).difference({-1})

Đầu ra: {4, 5, 7}


1

Đơn giản chỉ cần làm điều này:

def which_index(self):
    return [
        i for i in range(len(self.states))
        if self.states[i] == True
    ]

Cảm ơn bạn đã đóng góp và chào mừng bạn đến với StackOverflow. Tuy nhiên, vui lòng đọc Trợ giúp Chỉnh sửa để cải thiện định dạng của bạn và cũng thêm một số giải thích cho mã của bạn. Cảm ơn!
Sẽ
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.