Lập chỉ mục tất cả * ngoại trừ * một mục trong python


112

Có cách nào đơn giản để lập chỉ mục tất cả các phần tử của danh sách (hoặc mảng, hoặc bất cứ thứ gì) ngoại trừ một chỉ mục cụ thể không? Ví dụ,

  • mylist[3] sẽ trả lại hàng ở vị trí 3

  • milist[~3] sẽ trả về toàn bộ danh sách ngoại trừ 3

Câu trả lời:


111

Đối với một danh sách , bạn có thể sử dụng một comp danh sách. Ví dụ: để tạo bbản sao của akhông có phần tử thứ 3:

a = range(10)[::-1]                       # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
b = [x for i,x in enumerate(a) if i!=3]   # [9, 8, 7, 5, 4, 3, 2, 1, 0]

Điều này rất chung chung và có thể được sử dụng với tất cả các tệp lặp, bao gồm các mảng không có hạt. Nếu bạn thay thế []bằng (), bsẽ là một trình lặp thay vì một danh sách.

Hoặc bạn có thể làm điều này tại chỗ với pop:

a = range(10)[::-1]     # a = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
a.pop(3)                # a = [9, 8, 7, 5, 4, 3, 2, 1, 0]

Trong numpy, bạn có thể làm điều này với lập chỉ mục boolean:

a = np.arange(9, -1, -1)     # a = array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])
b = a[np.arange(len(a))!=3]  # b = array([9, 8, 7, 5, 4, 3, 2, 1, 0])

nói chung sẽ nhanh hơn nhiều so với việc hiểu danh sách được liệt kê ở trên.


52
>>> l = range(1,10)
>>> l
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> l[:2] 
[1, 2]
>>> l[3:]
[4, 5, 6, 7, 8, 9]
>>> l[:2] + l[3:]
[1, 2, 4, 5, 6, 7, 8, 9]
>>> 

Xem thêm

Giải thích ký hiệu lát cắt của Python


2
Câu trả lời tốt cho một danh sách. Bạn cũng có thể sử dụng nó cho các mảng nhưng bạn cần phải sử dụng numpy.concatenate.
Bi Rico

48

Cách đơn giản nhất mà tôi tìm thấy là:

mylist[:x]+mylist[x+1:]

điều đó sẽ tạo ra của bạn mylistmà không có phần tử tại chỉ mục x.


Tôi thấy điều này thực sự loại bỏ các mục x + 1, vẫn còn mặc dù hữu ích, thanks
Jack TC

24

Nếu bạn đang sử dụng numpy, gần nhất, tôi có thể nghĩ đến là sử dụng mặt nạ

>>> import numpy as np
>>> arr = np.arange(1,10)
>>> mask = np.ones(arr.shape,dtype=bool)
>>> mask[5]=0
>>> arr[mask]
array([1, 2, 3, 4, 5, 7, 8, 9])

Một cái gì đó tương tự có thể đạt được sử dụng itertoolsmà không cầnnumpy

>>> from itertools import compress
>>> arr = range(1,10)
>>> mask = [1]*len(arr)
>>> mask[5]=0
>>> list(compress(arr,mask))
[1, 2, 3, 4, 5, 7, 8, 9]

2
Tôi có thể sử dụng một cái gì đó như np.arange(len(arr)) != 3mặt nạ, bởi vì sau đó nó có thể được nội dòng, ví dụ arr[~(np.arange(len(arr)) == 3)]hoặc bất cứ điều gì.
DSM

@DSM: Vui lòng đăng bài này như một câu trả lời :-). Dù sao đi nữa, tôi cũng không thích Numpy lắm.
Abhijit

+1 để tạo mặt nạ cho một mảng, trong trường hợp là một danh sách, tôi sẽ đi với lát cắt và nối bằng cách sử dụng nén.
Bi Rico

5

Sử dụng np.delete! Nó không thực sự xóa bất cứ thứ gì tại chỗ

Thí dụ:

import numpy as np
a = np.array([[1,4],[5,7],[3,1]])                                       

# a: array([[1, 4],
#           [5, 7],
#           [3, 1]])

ind = np.array([0,1])                                                   

# ind: array([0, 1])

# a[ind]: array([[1, 4],
#                [5, 7]])

all_except_index = np.delete(a, ind, axis=0)                                              
# all_except_index: array([[3, 1]])

# a: (still the same): array([[1, 4],
#                             [5, 7],
#                             [3, 1]])

2

Tôi sẽ cung cấp một cách thực hiện chức năng (không thể thay đổi).

  1. Cách làm tiêu chuẩn và dễ dàng là sử dụng phương pháp cắt lát:

    index_to_remove = 3
    data = [*range(5)]
    new_data = data[:index_to_remove] + data[index_to_remove + 1:]
    
    print(f"data: {data}, new_data: {new_data}")

    Đầu ra:

    data: [0, 1, 2, 3, 4], new_data: [0, 1, 2, 4]
  2. Sử dụng khả năng hiểu danh sách:

    data = [*range(5)]
    new_data = [v for i, v in enumerate(data) if i != index_to_remove]
    
    print(f"data: {data}, new_data: {new_data}") 

    Đầu ra:

    data: [0, 1, 2, 3, 4], new_data: [0, 1, 2, 4]
  3. Sử dụng chức năng bộ lọc:

    index_to_remove = 3
    data = [*range(5)]
    new_data = [*filter(lambda i: i != index_to_remove, data)]

    Đầu ra:

    data: [0, 1, 2, 3, 4], new_data: [0, 1, 2, 4]
  4. Sử dụng mặt nạ. Tạo mặt nạ được cung cấp bởi hàm itertools.compress trong thư viện chuẩn:

    from itertools import compress
    
    index_to_remove = 3
    data = [*range(5)]
    mask = [1] * len(data)
    mask[index_to_remove] = 0
    new_data = [*compress(data, mask)]
    
    print(f"data: {data}, mask: {mask}, new_data: {new_data}")

    Đầu ra:

    data: [0, 1, 2, 3, 4], mask: [1, 1, 1, 0, 1], new_data: [0, 1, 2, 4]
  5. Sử dụng hàm itertools.filterfalse từ thư viện chuẩn Python

    from itertools import filterfalse
    
    index_to_remove = 3
    data = [*range(5)]
    new_data = [*filterfalse(lambda i: i == index_to_remove, data)]
    
    print(f"data: {data}, new_data: {new_data}")

    Đầu ra:

    data: [0, 1, 2, 3, 4], new_data: [0, 1, 2, 4]

0

Nếu bạn không biết trước chỉ mục thì đây là một hàm sẽ hoạt động

def reverse_index(l, index):
    try:
        l.pop(index)
        return l
    except IndexError:
        return False

0

Lưu ý rằng nếu biến là danh sách danh sách, một số cách tiếp cận sẽ không thành công. Ví dụ:

v1 = [[range(3)] for x in range(4)]
v2 = v1[:3]+v1[4:] # this fails
v2

Đối với trường hợp chung, sử dụng

removed_index = 1
v1 = [[range(3)] for x in range(4)]
v2 = [x for i,x in enumerate(v1) if x!=removed_index]
v2

0

Nếu bạn muốn cắt bỏ phần cuối cùng hoặc phần đầu tiên, hãy làm như sau:

list = ["This", "is", "a", "list"]
listnolast = list[:-1]
listnofirst = list[1:]

Nếu bạn thay đổi 1 thành 2, 2 ký tự đầu tiên sẽ bị loại bỏ chứ không phải ký tự thứ hai. Hy vọng điều này vẫn giúp ích!

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.