【问题标题】:Using variable tuple to access elements of list使用变量元组访问列表的元素
【发布时间】:2014-10-16 12:19:33
【问题描述】:

免责声明:初学者、自学 Python 用户。

ndarray 的一个非常酷的特性是它们能够接受整数元组作为索引(例如myNDArray[(1,2)] == myNDArray[1][2])。这允许我将未指定的索引保留为变量(例如 indicesTuple ),直到脚本确定要使用 ndarray 的哪个部分,在这种情况下,变量被指定为整数元组并用于访问 ndarray 的一部分(例如myNDArray[indicesTuple])。使用变量的效用是元组的长度可以根据 ndarray 的维度而变化。

但是,这限制了我使用数值数组。我尝试使用列表,但它们不能将元组作为索引(例如 myList[(1,2)] 给出错误。)。有没有办法像函数参数一样“解开”列表索引的元组?或者更简单或更高效的方法?

更新:天哪,我忘记了它的存在。基本上我最终了解到可以使用参数 dtype=object 初始化 ndarray,这允许 ndarray 包含多种类型的 Python 对象,就像一个列表。至于访问列表,正如评论者指出的那样,我可以使用 for 循环遍历变量 indicesTuple 来访问列表中越来越多的嵌套元素。对于就地编辑,请参阅接受的评论,那里确实做得更多。

【问题讨论】:

  • 原生 Python 索引符号 myList[1][2] 有什么问题?您为什么对通过元组进行索引感兴趣?
  • 我不能将它们作为变量保留在脚本中。我的代码更像 myList[myIndi​​ces]。编辑:编辑问题以反映这一点。
  • @BatWannaBe:你需要添加的只是一个循环。
  • 你提前知道元组有多大吗?例如,如果它总是两个元素长,你不能myList[tup[0]][tup[1]]吗?
  • 在使用您的 cmets 作为线索浏览 stackOverflow 之后,我发现我总是可以使用带有 dtype = object 的 ndarrays,有效地使 ndarrays 列表能够包含任何类型的对象。

标签: python list tuples indices


【解决方案1】:

我将您的问题解释为:

我有一个 N 维列表和一个包含 N 个值(T1、T2...TN)的元组。如何使用元组值访问列表?我不知道N会提前多少。

我不知道执行此操作的内置方法,但您可以编写一个迭代挖掘列表直到到达最里面的值的方法。

def get(seq, indices):
    for index in indices:
        seq = seq[index]
    return seq

seq = [
    [
        ["a","b"],
        ["c","d"]
    ],
    [
        ["e","f"],
        ["g","h"]
    ]
]

indices = [0,1,0]
print get(seq, indices)

结果:

c

您也可以使用reduce 在一行* 中执行此操作,尽管读者不太清楚您要完成什么。

print reduce(lambda s, idx: s[idx], indices, seq)

(*如果您使用的是 3.X,则需要从 functools 导入 reduce。所以,两行。)


如果您想设置 N 维列表中的值,请使用get 访问列表的第二深层,并分配给它。

def set(seq, indices, value):
    innermost_list = get(seq, indices[:-1])
    innermost_list[indices[-1]] = value

【讨论】:

  • 这就是我的想法,但我需要更改原始列表本身,而不是从中获取值。所以我需要类似 myList[T1],[T2]...[TN] = newValue.
【解决方案2】:

假设你有一个(i,j) 索引列表

indexList = [(1,1), (0,1), (1,2)]

还有一些你想要索引的二维列表

l = [[1,2,3],
     [4,5,6],
     [7,8,9]]

您可以使用列表推导式获取这些元素,如下所示

>>> [l[i][j] for i,j in indexList]
[5, 2, 6]

然后你的索引可以是你想要的任何东西。它们将在列表理解中解包,并用作列表索引。对于您的特定应用程序,我们必须查看您的索引变量的来源,但这是一般的想法。

【讨论】:

    【解决方案3】:

    Python 没有多维列表,因此myList[(1,2)] 只能被视为(myList[1], myList[2]) 的快捷方式(有时这会非常方便,尽管您可以使用import operator; x = operator.itemgetter(1,2)(myList) 来完成同样的操作)。

    如果您的 myList 看起来像

    myList = [ ["foo", "bar", "baz"], ["a", "b", c" ] ]
    

    那么myList[(1,2)] 将不起作用(或有意义),因为myList 不是二维列表:它是一个包含对列表的引用的列表。您使用myList[1][2] 是因为第一个索引myList[1] 返回对["a", "b", "c"] 的引用,您将第二个索引[2] 应用到该引用以获取"c"

    有点相关,您可以使用字典来精确模拟稀疏数组,方法是使用元组作为默认字典的键。

    import collections
    d = collections.defaultdict(str)
    d[(1,2)] = "foo"
    d[(4,5)] = "bar"
    

    您尝试用作键的任何其他元组都将返回空字符串。这不是一个完美的模拟,因为如果不使用类似的东西,您将无法访问数组的完整行或列

    row1 = [d[1, x] for x in range(C)] # where C is the number of columns
    col3 = [d[x, 3] for x in range(R)] # where R is the number of columns
    

    【讨论】:

      【解决方案4】:

      使用元组索引的字典

      >>> width, height = 7, 6
      >>> grid = dict(
              ((x,y),"x={} y={}".format(x,y))
              for x in range(width)
              for y in range(height))
      >>> print grid[3,1]
      x=3 y=1
      

      使用列表列表

      >>> width, height = 7, 6
      >>> grid = [
              ["x={} y={}".format(x,y) for x in range(width)]
              for y in range(width)]
      >>> print grid[1][3]
      x=3 y=1
      

      在这种情况下,您可以创建一个 getter 和 setter 函数:

      def get_grid(grid, index):
          x, y = index
          return grid[y][x]
      
      def set_grid(grid, index, value):
          x, y = index
          grid[y][x] = value
      

      您可以更进一步,创建您自己的包含列表列表的类,并定义一个将元组作为索引的索引器并执行相同的过程。与字典相比,它可以进行更明智的边界检查并提供更好的诊断,但需要进行一些设置。我认为字典方法非常适合快速探索。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-03-30
        • 1970-01-01
        • 1970-01-01
        • 2012-11-26
        • 2017-09-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多