HOWTO · NumPy

在 NumPy 陣列中查詢元素的第一個索引

本教程演示瞭如何在 python 中查詢陣列中元素的索引

本頁內容

若要在一維 NumPy 陣列中尋找某個值的第一個索引,且確定一定有符合項目,可以使用 np.where(array == value)[0][0]。這個運算式會回傳第一個符合的位置;若該值可能不存在,請先檢查是否有符合項目。NumPy 索引從零開始。

使用 np.where() 尋找第一個符合的索引

np.where(condition) 會回傳一個 tuple,其中包含各維度的索引陣列。對一維陣列而言,tuple 的第一個項目就是所有符合位置的清單。選取其中第一個位置即可取得第一筆符合項目。

執行以下範例:

本節中的程式碼以及顯示的標籤或輸出仍為英文。

import numpy as np

values = np.array([10, 20, 30, 40, 50, 20])
target = 20
matches = np.where(values == target)[0]
print(int(matches[0]))
1

在此,matches 包含 20 出現的兩個位置,而 matches[0] 會選取第一個位置。若沒有任何值符合條件,matches 就不會有元素,因此進行索引時會引發 IndexError。如果不確定是否有符合項目,請先檢查 matches.size 再選取索引。三個引數的形式 np.where(condition, x, y) 則會依條件從 x 或 y 選取值;這與此處用來回傳索引的形式不同。

使用 np.nonzero() 尋找符合的索引

對布林條件使用 np.nonzero() 時,它會回傳值為 True 的項目索引。和單一引數形式的 np.where() 一樣,它會回傳由索引陣列組成的 tuple,每個陣列維度各有一個索引陣列。若陣列是一維,取用 tuple 中的第一個陣列即可。

本節中的程式碼以及顯示的標籤或輸出仍為英文。

import numpy as np

values = np.array([4, 7, 4, 9])
positions = np.nonzero(values == 4)[0]
print(positions.tolist())

結果會依陣列中的順序包含所有符合的位置。只有在確認陣列非空後,才能使用 positions[0] 取得第一個符合項目。對多維陣列而言,tuple 中的每個項目都包含某一維度的座標;將對應位置配對,即可定位每個符合項目。

使用 np.argmax() 尋找布林符合項目

np.argmax() 會回傳最大值的位置。套用在布林遮罩上時,它會回傳第一個 True 的位置,因為 True 大於 False。全為 False 的遮罩也會得到 0,因此使用結果前請先確認確實有符合項目。

本節中的程式碼以及顯示的標籤或輸出仍為英文。

import numpy as np

values = np.array([5, 8, 3, 8])
mask = values == 8
first = int(np.argmax(mask)) if np.any(mask) else None
print(first)

這種寫法在目標不存在時會得到 None,否則會回傳第一個符合的位置。若要取得所有符合位置,請改用 np.where() 或 np.nonzero()。

將陣列轉換後使用 list.index()

將一維陣列轉換成 Python 清單後,就能使用清單方法 list.index()。它會回傳值第一次出現的位置。轉換會建立一個 Python 清單,因此會增加時間與記憶體成本;對小型陣列或原本就在使用清單的程式而言,這種方式通常最方便。

本節中的程式碼以及顯示的標籤或輸出仍為英文。

import numpy as np

values = np.array([10, 20, 30, 20])
items = values.tolist()
target = 20
index = items.index(target) if target in items else None
print(index)

先檢查是否包含該值,就能明確地在找不到時回傳 None;若值不存在卻直接呼叫 items.index(target),則會引發 ValueError。檢查與查找都會各自掃描清單,因此若只查找一次,也可以在呼叫 list.index() 時捕捉 ValueError。

使用迴圈處理自訂邏輯

當每個元素都需要套用不容易用 NumPy 向量化條件表達的自訂檢查時,迴圈就很實用。先將結果初始化為代表找不到的值,再於找到第一個符合項目時立即停止。

本節中的程式碼以及顯示的標籤或輸出仍為英文。

import numpy as np

values = np.array([12, 15, 18, 21])
index = None

for position, value in enumerate(values):
    if value % 2 == 0 and value > 12:
        index = position
        break

print(index)

迴圈會逐一檢查元素,並在第一個同時符合兩項條件的值出現時結束。若只是檢查是否相等,使用 NumPy 遮罩通常更精簡;當比對規則需要自訂分支或狀態時,則可使用迴圈。

處理找不到符合項目、重複值與陣列維度

請依照任務選擇適合的結果形式:

  • 若要找一維陣列中的第一個符合項目,使用 np.where() 或 np.nonzero() 取得位置,確認至少有一個位置,再選取第一個。
  • 若要取得所有符合項目,請保留完整索引陣列。重複值會對應到多個位置;需要全部結果時,不要只選取 [0]。
  • 對二維陣列而言,np.where(matrix == target) 會回傳 (row_indices, column_indices)。對應項目會組成座標配對。例如,(rows[0], columns[0]) 是第一個符合項目的列與欄座標,不是單一的扁平索引。
  • 若確實需要多維陣列中的扁平位置,請先將陣列攤平,再搜尋攤平後的值。必要時可使用 np.unravel_index() 將扁平位置轉回座標。
  • 對非空且全為 False 的遮罩,np.argmax() 會回傳零,但該位置不代表有符合項目。若遮罩是空的,np.argmax() 則會引發 ValueError。上方的防護運算式會先檢查 np.any(mask),因此無論遮罩是沒有任何 True 值,或是空遮罩,都會回傳 None。

對一般數值陣列查找而言,需要第一個或所有符合項目時,np.where() 是直接的選擇。若要取得條件為 True 的相同位置,也可使用 np.nonzero();對布林遮罩使用 np.argmax() 時,請先確認有符合項目;若程式已在使用 Python 清單,可採用 list.index();需要自訂比對規則時,則可使用迴圈。