Buat indeks semua * kecuali * satu item dengan python


113

Apakah ada cara sederhana untuk mengindeks semua elemen daftar (atau larik, atau apa pun) kecuali untuk indeks tertentu? Misalnya,

  • mylist[3] akan mengembalikan item di posisi 3

  • milist[~3] akan mengembalikan seluruh daftar kecuali 3

Jawaban:


112

Untuk daftar , Anda bisa menggunakan daftar comp. Misalnya, untuk membuat bsalinan atanpa elemen ke-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]

Ini sangat umum, dan dapat digunakan dengan semua iterable, termasuk array numpy. Jika Anda mengganti []dengan (), bakan menjadi iterator, bukan daftar.

Atau Anda dapat melakukan ini di tempat dengan 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]

Secara numpy Anda dapat melakukan ini dengan pengindeksan 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])

yang secara umum akan jauh lebih cepat daripada pemahaman daftar yang tercantum di atas.


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]
>>> 

Lihat juga

Jelaskan notasi irisan Python


2
Jawaban yang bagus untuk sebuah daftar. Anda juga dapat menggunakannya untuk array, tetapi Anda harus menggunakannya numpy.concatenate.
Bi Rico

48

Cara paling sederhana yang saya temukan adalah:

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

yang akan menghasilkan Anda mylisttanpa elemen di index x.


Saya menemukan ini sebenarnya menghapus item x + 1, meskipun masih berguna, terima kasih
Jack TC

24

Kalau pakai numpy, yang paling bisa terpikir oleh saya adalah pakai masker

>>> 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])

Hal serupa dapat dicapai dengan menggunakan itertoolstanpanumpy

>>> 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
Saya mungkin menggunakan sesuatu seperti np.arange(len(arr)) != 3sebagai topeng, karena itu bisa disisipkan, misalnya arr[~(np.arange(len(arr)) == 3)]atau apapun.
DSM

@DSM: Silakan posting ini sebagai jawaban :-). Bagaimanapun, saya tidak begitu paham dengan Numpy.
Abhijit

1 untuk menutupi array, dalam kasus daftar saya akan menggunakan slice dan concatenate menggunakan kompres.
Bi Rico

5

Gunakan np.delete! Itu tidak benar-benar menghapus apa pun di tempat

Contoh:

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

Saya akan memberikan cara yang fungsional (tidak dapat diubah) untuk melakukannya.

  1. Cara standar dan mudah untuk melakukannya adalah dengan mengiris:

    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}")

    Keluaran:

    data: [0, 1, 2, 3, 4], new_data: [0, 1, 2, 4]
  2. Gunakan pemahaman daftar:

    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}") 

    Keluaran:

    data: [0, 1, 2, 3, 4], new_data: [0, 1, 2, 4]
  3. Gunakan fungsi filter:

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

    Keluaran:

    data: [0, 1, 2, 3, 4], new_data: [0, 1, 2, 4]
  4. Menggunakan masking. Masking disediakan oleh fungsi itertools.compress di pustaka standar:

    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}")

    Keluaran:

    data: [0, 1, 2, 3, 4], mask: [1, 1, 1, 0, 1], new_data: [0, 1, 2, 4]
  5. Gunakan fungsi itertools.filterfalse dari pustaka standar 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}")

    Keluaran:

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

0

Jika Anda tidak mengetahui indeks sebelumnya di sini adalah fungsi yang akan berfungsi

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

0

Perhatikan bahwa jika variabel adalah daftar daftar, beberapa pendekatan akan gagal. Sebagai contoh:

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

Untuk kasus umum, gunakan

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

Jika Anda ingin memotong yang terakhir atau yang pertama lakukan ini:

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

Jika Anda mengubah 1 menjadi 2, 2 karakter pertama akan dihapus, bukan yang kedua. Semoga ini masih membantu!

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.