如何在Python中进行二维(x,y)索引?

3 投票
3 回答
3515 浏览
提问于 2025-04-17 17:32

一般来说,如果你有一个二维的数据结构,它通常是由两个容器组合而成的,比如一个列表里面装着多个列表,或者一个字典里面装着多个字典。那么,如果你想要创建一个单一的集合,但又想以二维的方式来操作它,该怎么做呢?

不要这样做:

collection[y][x]

而是这样做:

collection[x,y]

我知道这是可能的,因为PIL Image.load 函数返回的对象就是以这种方式工作的。

3 个回答

0

我在Python邮件列表上找到了这个方法。通过这个方法,你可以用索引的迭代器来访问容器里的元素。如果你需要使用container[index_1, index_2]这种写法,可以根据Mark的帖子里提到的方法轻松调整。

>>> from operator import getitem
>>> from functools import reduce
>>> l = [1,[2,[3,4]]]
>>> print(reduce(getitem, [1,1,1], l))
 4

这里有一个在Python邮件列表上建议的不同方法,我把它调整成了container[index_1, index_2]的写法。

class FlatIndex(object):
  def __init__(self, l):
    self.l = l
  def __getitem__(self, key):
    def nested(l, indexes):
      if len(indexes) == 1:
        return l[indexes[0]]
      else:
        return nested(l[indexes[0]], indexes[1:])
    return nested(self.l, key)

>>> l = [1,[2,[3,4,[5,6]]]] 
>>> a = FlatIndex(l)
>>> print(a[1,1,2,1])
 6
1

使用 numpy 数组。

如果你有一个普通的 Python 数组,你可以把它转换成 numpy 数组,然后像你描述的那样访问它的元素:

a = [[1,2,3],[4,5,6],[7,8,9]]
A = numpy.array(a)
print A[1,1]

这将打印出:

5

另一个例子:

A = numpy.zeros((3, 3))
for i in range(3):
    for j in range(3):
        A[i,j] = i*j
print A

这将给你:

[[ 0.  0.  0.]
 [ 0.  1.  2.]
 [ 0.  2.  4.]]
7

关键是要理解Python是如何进行索引的。当你用方括号[]去索引一个对象时,Python会调用这个对象的__getitem__方法。感谢这个回答让我找到了方向:创建一个可以用方括号访问的Python对象

当你在方括号中使用一对索引时,__getitem__方法会接收到一个元组作为key参数。

下面是一个简单的演示类,当给定一个二维索引时,它会返回一维列表中的整数索引。

class xy(object):

    def __init__(self, width):
        self._width = width

    def __getitem__(self, key):
        return key[1] * self._width + key[0]

>>> test = xy(100)
>>> test[1, 2]
201
>>> test[22, 33]
3322

还有一个配套的__setitem__方法,当你想给方括号中的索引赋值时会用到这个方法。

撰写回答