线性索引、逻辑索引以及所有这些

36

在Matlab中,我们习惯使用不同形式的索引:

  • 标准索引(沿每个维度使用整数),
  • 逻辑索引(使用逻辑值),
  • 线性索引(使用单个索引来遍历具有多个维度的数组)。

乍一看,这些形式似乎是互相排斥的:索引要么是标准的,要么是逻辑的,要么是线性的。然而,有时它们之间会出现混合。例如,

>> A = magic(3)
A =
     8     1     6
     3     5     7
     4     9     2
>> A(A>5)
ans =
     8
     9
     6
     7

这是逻辑索引,对吧?但它也具有线性索引的某些特点,因为它返回了一个列向量。实际上,逻辑索引A>5与线性索引find(A>5)具有相同的效果。

作为第二个例子,考虑以下:

>> A = magic(3)
A =
     8     1     6
     3     5     7
     4     9     2
>> A(1:2, [true false true])
ans =
     8     6
     3     7

在此表达式中,第一个坐标使用标准(整数值)索引,第二个坐标使用逻辑索引。

这些示例(以及在实践中出现的更复杂的示例)引发以下问题:

  • Matlab中有哪些类型的索引?
  • 它们如何组合?
  • 应该如何引用它们?
1个回答

42
以下内容中我使用了与标准Matlab实践更或多或少一致的术语。但在某些情况下,我不得不杜撰一个名称,因为我不知道现有的名称。如果有比我使用的更标准的名称,请告诉我。
本答案旨在澄清不同类型的索引以及如何组合它们。另一个问题是根据索引变量的形状确定输出数组的形状size)函数。Loren Shure在Essence of indexing中发表了一篇好文章。
以下描述重点讨论了数字数组的索引,但可以应用于使用括号或花括号索引的单元格数组,相应地改变输出类型(单元格数组或逗号分隔列表),这将在最后简要讨论。

数字数组的索引类型

考虑以下两个属性,可以对索引进行分类。
  1. 根据每个索引变量所涉及的维度数量,索引可以是多维的或线性的。但这只是两种极端情况。存在一种中间情况,可能被称为部分线性索引:

    • 纯多维 索引为数组的每个维度指定一个索引变量。 Matlab 文档有时将这些单独的索引称为 下标 (例如查看sub2ind)。
    • 纯线性 索引指定一个单一的索引变量,它跨越所有维度遍历数组(可以视为所有维度都折叠成一个)。正如我们所知道的,遍历首先沿列进行,然后沿行进行,然后沿第三个维度片遍历等(所谓的列主序)。
    • 部分线性 索引:给定一个具有 m+n 维度,其中 n>=2 的数组,可以为前 m 个维度指定 m 个索引变量(因此在这些维度中使用多维索引),并为最后 n 个维度指定一个索引变量,它仅在这些维度上被解释为线性索引(最后的 n 个维度折叠成一个)。
  2. 根据索引值的类型,每个索引变量可以是整数值或逻辑值:

    • 如果索引变量包含正整数,则为整数值
    • 如果索引变量包含逻辑值,则为逻辑值

分类标准1和2是独立的。从标准1的角度来看,索引的类别与其根据标准2的类别无关。所有组合都是可能的。

因此,根据上述分类,有6种基本索引类型。为了澄清,以下是每个示例。所有示例都使用数组 A = cat(3, magic(3), 9+magic(3)),即

A(:,:,1) =
     8     1     6
     3     5     7
     4     9     2
A(:,:,2) =
    17    10    15
    12    14    16
    13    18    11
  1. Multidimensional, integer-valued:

    >> A([1 2], 2, 2)
    ans =
        10
        14
    
  2. Linear, integer-valued:

    >> A([2 5:7])
    ans =
         3     5     9     6
    
  3. Partially linear, integer-valued:

    >> A([1 2], 2:4)
    ans =
         1     6    17
         5     7    12
    
  4. Multidimensional, logical:

    >> A([true true false], [false true false], [false true])
    ans =
        10
        14
    

    Interestingly, the number of logical values may be smaller, or even larger, than the size in the dimension the index refers to:

    >> A([true true], [false true false false], [false true])
    ans =
        10
        14
    

    Missing values are interpreted as false, and surplus values must be false or an error will occur. See for example this page by Mathworks or this answer by Jonas.

  5. Linear, logical:

    >> A([false true false false true true true])
    ans =
         3     5     9     6
    

    (Note that 11 trailing false values have been left out in the indexing vector.)

  6. Partially linear, logical:

    >> A([true true false], [false true true true false false])
    ans =
         1     6    17
         5     7    12
    

在多维或部分线性索引中,存在多个索引变量,每个变量可以独立地是整数或逻辑类型。这会产生不同的混合类型。例如:

  1. Multidimensional, logical/integer-valued:

    >> A([true false true], [false true true], 2)
    ans =
        10    15
        18    11
    
  2. Partially linear, integer-valued/logical:

    >> A([1 2], [true false true false true false])
    ans =
         8     6    10
         3     7    14
    
如果被索引的数组是一个稀疏矩阵,那么上述所有内容仍然适用,除了部分线性索引不存在于矩阵中;当然,结果也是稀疏的。

单元数组索引

所有针对数值数组的索引类型都可以应用于单元数组,但需要额外考虑一点。单元数组可以使用圆括号或花括号进行索引。在第一种情况下,索引的结果是一个单元数组。在第二种情况下,它是一个由单元格内容组成的逗号分隔列表。

举个例子,假设前面示例中使用的数值数组转换为单元数组C = num2cell(A),即

C(:,:,1) = 
    [8]    [1]    [6]
    [3]    [5]    [7]
    [4]    [9]    [2]
C(:,:,2) = 
    [17]    [10]    [15]
    [12]    [14]    [16]
    [13]    [18]    [11]

那么在上述示例8中使用的索引将产生一个单元数组:

>> C([1 2], [true false true false true false])
ans = 
    [8]    [6]    [10]
    [3]    [7]    [14]

如果使用花括号,将得到逗号分隔的列表。

>> C{[1 2], [true false true false true false]}
ans =
     8
ans =
     3
ans =
     6
ans =
     7
ans =
    10
ans =
    14 

精简版 / TL;DR

逻辑索引和线性索引并不是互斥的索引类型,它们是独立的索引特征。"逻辑"指的是索引值的类型,而"线性"表示多个维度被合并为一个进行索引。这两种特征可以同时发生。


我最初认为这将是此问答的重复。但实际上并不是,但无论如何它们高度相关。我会包含这个答案,因为它解释了所有与错误索引相关的错误。 - Robert Seifert
@thewaywewalk,我觉得那个问答跟这个问题关系不大。那个问答是处理由于索引具有不当值或变量名称遮蔽函数而导致的错误。而这个问题是关于存在的不同类型的索引,根据两个标准进行分类,并试图强调这两个标准是独立的。 - Luis Mendo
昨天发现了一件有趣的事情,简化版如下:x=rand(1,10);y=x(magic(3))。使用一个3x3的线性整数索引来索引一个向量,最终得到一个3x3的矩阵。 - Daniel
1
@Daniel 是的,关于输出的形状,我在我的回答中提供的这篇文章非常全面。 - Luis Mendo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接