配列スライシング

ウィキペディアから、無料の百科事典
ナビゲーションにジャンプ 検索にジャンプ

コンピュータプログラミングでは配列スライシングは、配列から要素のサブセットを抽出し、それらを別の配列として、場合によっては元の配列とは異なる次元でパッケージ化する操作です。

配列スライシングの一般的な例は、文字列からの部分文字列の抽出、 h ello」の「ell」 2次元配列からの行または列の抽出、または行列からのベクトルの抽出です。

プログラミング言語によっては、連続しない要素から配列スライスを作成できます。また、言語によっては、新しい配列の要素が元の配列の要素にエイリアスされる(つまり、メモリを共有する)場合があります。

詳細

「1次元」(単一インデックス)配列(ベクトル、シーケンス、文字列など)の場合、最も一般的なスライス操作は、0個以上の連続する要素の抽出です。したがって、要素(2、5、7、3、8、6、4、1)を含むベクトルがあり、3番目から6番目の項目までの配列スライスを作成する場合、(7、3、 8、6)。0ベースのインデックススキームを使用するプログラミング言語では、スライスはインデックス2から5になります。

任意のインデックスの範囲を単一の値に減らすと、そのインデックスが効果的に削除されます。この機能は、たとえば、3次元配列から1次元スライス(ベクトル:3D、行、列、およびチューブ[1])または2次元スライス(長方形行列)を抽出するために使用できます。ただし、範囲は実行時に指定できるため、型チェックされた言語では、些細なインデックスを実際に削除するために明示的な(コンパイル時の)表記が必要になる場合があります。

一般的な配列スライシングは、ドープベクトルまたは記述子 (最初の配列要素のアドレス、次に各インデックスの範囲と対応する係数を含むレコード)を介してすべての配列を参照することにより、(言語に組み込まれているかどうかに関係なく)実装できます。インデックス作成式。この手法では、配列の即時転置、インデックスの反転、サブサンプリングなども可能です。インデックスが常にゼロから始まるCのような言語の場合、 d個のインデックスを持つ配列のドープベクトルには少なくとも1 + 2d個のパラメーターがあります。Pascalのように、インデックスに任意の下限を許可する言語の場合、ドープベクトルには1 + 3dが必要です。エントリ。

配列の抽象化が真の負のインデックスをサポートしていない場合(たとえば、AdaPascalの配列がサポートしている場合)、特定の次元のスライスの境界の負のインデックスを使用して、配列の末尾からのオフセットを指定することがあります。その次元。1ベースのスキームでは、-1は通常、最後から2番目のアイテムを示しますが、0ベースのシステムでは、最後のアイテムを意味します。

歴史

スライスの概念は、コンパイラが発明される前から確かに知られていました。言語機能としてのスライスは、おそらくFORTRAN (1957)から始まりました。これは、設計によるよりも、存在しないタイプと範囲のチェックの結果です。この概念は、IALの予備レポート(ALGOL 58)でもほのめかされており、構文では、実際の要素として使用するときに、配列要素(または、さらに言えば、プロシージャ呼び出し)の1つ以上のインデックスを省略できます。パラメータ。

Kenneth IversonAPL(1957)は、非常に柔軟な多次元配列スライシングを備えていたため、言語の表現力と人気に大きく貢献しました。

ALGOL 68(1968)は、包括的な多次元アレイスライシングおよびトリミング機能を導入しました。

配列スライシング機能は、 Ada 2005CobraDFortran 90GoRustJuliaMATLABPerlPythonS-LangWindows PowerShell、数学/統計言語GNU Octaveなど、いくつかの最新言語に組み込まれています。 SR。 _

さまざまなプログラミング言語でのスライスのタイムライン

1966年:Fortran66

Fortran 66プログラマーは、行ごとに行列をスライスすることだけを利用でき、その行をサブルーチンに渡すときにのみ利用できました。

      SUBROUTINE PRINT V VEC  LEN 
REAL VEC * PRINT * VEC I )、I = 1 LEN END        
              
      

      プログラムメイン
パラメータLEN = 3 REAL MATRIX LEN LEN DATA MATRIX / 1、1、1、2、4、8、3、9、27 / CALL PRINT V MATRIX 1、2 LEN END _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _          
         
                
          
      

結果:

   2.000000 4.000000 8.000000

FORTRAN 66にはドープベクトルがないため、スライスの長さも引数(またはその他の手段)としてに渡される必要があることに注意してくださいSUBROUTINE1970年代のPascalCにも同様の制限がありました。

1968年:Algol68

Algol68の最終レポートには、スライスの初期の例が含まれています。スライスは次の形式で指定されます。

[下限:上限] ¢拡張文字セットを備えたコンピューターの場合¢

また:

(下限..上限)#6ビット文字のみのコンピューターの場合。

両方の境界は包括的であり、省略できます。その場合、デフォルトで宣言された配列境界になります。ストライド機能も対角スライスエイリアスも、改訂されたレポートの一部ではありません。

例:

[3、3] real a:=((1、1、1)、(2、4、8)、(3、9、27)); #変数行列の宣言# 
[、] real c =((1、1、1)、(2、4、8)、(3、9、27));   #定数マトリックス、サイズが暗黙指定されます#
ref [] real row:= a [2、];                    #行スライスへのエイリアス/参照
#ref [] real col2 = a [、2];                   #永続的なエイリアス/ 2番目の列への参照
印刷((a [:、2]、改行));                #2番目の列のスライス
#print((a [1⌈a、:]、newline));              #最後の行のスライス
#print((a [:、2⌈a]、newline));              #最後の列スライス#print 
((a [:2、:2]、newline));              #先頭の2行2列の部分行列「スライス」#
+1.0000 10 +0 +4.0000 10 +0 +9.0000 10 +0
+3.0000 10 +0 +9.0000 10 +0 +2.7000 10 +1
+1.0000 10 +0 +8.0000 10 +0 +2.7000 10 +1
+1.0000 10 +0 +1.0000 10 +0 +2.0000 10 +0 +4.0000 10 +0

1970年代:MATLAB

>  A  =  round rand 3、4、5  * 10 %3x4x53次元または3次元配列> A(:、:、3 3x41次元 および2次元に沿っ2次元配列 
    

ans  =

  8   3   5   7 
  8   9   1   4 
  4   4   2   5

>  A (:、 2 3、3 1次元および2次元に沿った3x22次元配列  

ans  =

  3  5 
  9  1 
  4  2

>  A 2 end  :、 3  %2x42次元配列'end'キーワードを使用; GNUOctave3.2.4で動作します

ans  =

   6     1     4     6 
  10     1     3     1

>  A 1  :、 3  %2次元に沿った1次元配列

ans  =

  8   3   5   7

>  A 1、2、3 単一ans = 3 _  _  
  

1976:S / R

SおよびGNURの配列は常に1ベースであるため、新しいスライスのインデックスは、以前のインデックスに関係なく、次元ごとに1つで始まります。長さが1のディメンションはドロップされます(ドロップ= FALSEの場合を除く)。ディメンション名(存在する場合)は保持されます。

> A  <- 配列1 60  dim  =  c 3、4、5  #3x4x53次元または3次元配列> A [ 、、3 ]  1次元および2次元沿った3x4 2次元配列     [、1 ] [、2] [、3] [、4] [1、] 25 28 31 34 [2、] 26 29 32 35 [ 3 、] 27 30 33 36 > A [ 2 3、3 ドロップ= FALSE ] 
   




      #3x2x1 3次配列サブセット(保存された次元)、、
1

     [、1] [、2] 
[1、] 28 31 
[2、] 29 32 
[3、] 30 33 
> A [、 2、3 ] 1次元に沿った1次元配列[1] 28 29 30 > A [ 1、2、3 ] 単一の値[ 1 ] 28   

   

1977:Fortran77

Fortran 77標準では、文字列 をスライスして連結する機能が導入されました。

プログラムメイン
  プリント *  'ABCDE' 2 4 
END

生産:

BCD

このような文字列は、別のサブルーチンを参照して渡すことができ、長さも一種の短いドープベクトルとして透過的にサブルーチンに渡されます。

サブルーチンプリントS STR 
  文字 * * STR
  プリント *  STR 
END

プログラムメイン
  コールプリントS 'ABCDE' 2 4 ))
END

再び生成します:

BCD

1979年:Sinclair BASIC ZX80 / 81 /Spectrum

ZX80 / 81 / Spectrumの標準ROMは、文字列 をスライスおよび連結する機能を備えたBASICを提供します。

必要な配列スライスを示すコマンド部分(x TO y)では、x値とy値を省略して、すべての連鎖配列セル(FROM x TO end)または(begin TO y)を使用する意味を与えることができます。多次元配列では、スライスは最後のレベルの次元でのみ可能です。

10 LET a $ = "ABCDE" 2から4 20 PRINT a $    
  

生産:

BCD
10 LET a $ = "ABCDE" 20 LET b $ = a $ 4 TO + a $ 2 TO 3 + a $ 1 30 PRINT b $  
     
  

生産:

DEBCA

1983年:エイダ83以上

Ada 83は、すべてのアレイタイプのスライスをサポートしています。Fortran 77のように、そのような配列は別のサブルーチンへの参照によって渡される可能性があり、長さも一種の短いドープベクトルとしてサブルーチンに透過的に渡されます。

 Text_IOを使用;
 
プロシージャ メイン 
   テキスト  文字列 :=  "ABCDE" ; 
Text_IOを開始します
   Put_Line Text 2 .. 4 )); メインを終了します;    
 

生産:

BCD

注: AdaではインデックスはnベースであるText (2 .. 4)ため、この用語はベースインデックスが2の配列になります。

の定義Text_IO.Put_Lineは次 のとおりです。

パッケージ Ada.Text_IO 
   
   プロシージャ Put_Line アイテム 文字列  );

の定義Stringは次 のとおりです。

パッケージ 標準 

   サブタイプ Positive  整数 範囲 1 です.. 整数'最後;

   タイプ 文字列  文字の配列 の範囲 <>) です ; プラグマパック文字列);
    

Adaは真の負のインデックスをサポートしtype History_Data_Array is array (-6000 .. 2010) of History_Data;ているため、負のインデックスに特別な意味はありません。上記の例では、この用語は紀元前31年から紀元前30 Some_History_Data (-30 .. 30)までをスライスします(ゼロ年がなかったため、0年は実際には紀元前1年を指します)。 History_Data

1987:Perl

私たちが持っている場合

@a  =  2、5、7、3、8、6、4 ; _  _ _  _ _  _ _  _ _  _ _ 

上記のように、最初の3つの要素、中央の3つの要素、最後の3つの要素は次のようになります。

@a [ 0 .. 2 ];    #(2、5、7)
@a [ 2 .. 4 ];    #(7、3、8)
@a [ -3 ..- 1 ] ; #(8、6、4) 

Perlは負のリストインデックスをサポートしています。-1インデックスは最後の要素、-2は最後から2番目の要素などです。さらに、Perlは式に基づくスライスをサポートしています。次に例を示します。

@a [  3 ..  $#a  ];    #最後までの4番目の要素(3、8、6、4)
@a [  grep  {  $ _   3  }  0 ... $#a  ];     #1番目、4番目、7番目の要素(2,3,4)
@a [  grep  {  (($ _ + 1   3  }  0 .. $#a  ];  #3番目の要素ごと(7,6)

1991:Python

次のリストがある場合:

>>> nums  =  [ 1、3、5、7、8、13、20 ] _  _ _  _ _  _ _  _ _  _ _  _

次に、要素の取得と同様の表記法を使用してスライスすることができます。

>>> nums [ 3 ]    #スライスなし
7 
>>> nums [:3 ]   #インデックス0(包括的)からインデックス3(排他的)まで
[1、3、5] 
>>> nums [ 1 5 ] 
[3 、5、7、8] 
>>> nums [ -3 :] [ 8、13、20 ]

Pythonでは負のリストインデックスが許可されていることに注意してください。インデックス-1は最後の要素、-2は最後から2番目の要素などを表します。Pythonでは、追加のコロンと値を追加することでstepプロパティを使用することもできます。例えば:

>>> nums [ 3 :] 
[7、8、13、20] 
>>> nums [ 3 ::]  #== nums [3:] 
[7、8、13、20] 
>>> nums [::3 ]  #インデックス0から開始し、3つおきの要素を取得[1、7、20 
] 
>>> nums [ 1 5 2 ]  #インデックス1からインデックス5まで、2つおきの要素を取得[3、7 
]

ストライド構文(nums[1:5:2])は、Pythonの「matrix-SIG」(分科会)の科学ユーザーからのリクエストの結果として、1990年代の後半に導入されました。[2]

スライスのセマンティクスは、オブジェクトごとに異なる可能性があります。演算子がインデックス演算子をオーバーロードするときに、新しいセマンティクスを導入できます。Python標準リスト(動的配列)では、すべてのスライスがコピーになります。対照的に、 NumPy配列 のスライスは、同じ基になるバッファーへのビューです。

1992:Fortran90以降

Fortran 90では、スライスは次の形式で指定されます。

lower_bound upper_bound [:stride ]

両方の境界は包括的であり、省略できます。その場合、デフォルトで宣言された配列境界になります。ストライドのデフォルトは1です。例:

実数 次元m  n ::  a   行列の宣言
  
印刷 *  a (:、 2  2列目
印刷 *  a m  :)  最後の行の
印刷 *  a (:10  10  主要な10行10列の部分行列

1994:Analytica

Analyticaの配列値の各次元は、Index変数によって識別されます。スライスまたはサブスクリプトを作成する場合、構文は、ディメンションに名前を付けることにより、スライスまたはサブスクリプトを作成するディメンションを識別します。そのような:

インデックスI:=1..5{数値インデックスの定義}
インデックスJ:= ['A'、'B'、'C']{テキスト値のインデックスの定義}
変数X:= Array(I、J、[[10、20、30]、[1、2、3]、....]){2D値の定義}
X [I = 1、J ='B']->20{単一の値を取得するための添え字}
X [I = 1]-> Array(J、[10、20、30]){1D配列をスライスします。}
X [J = 2]-> Array(I、[20、2、....]){1D配列を他の次元にスライスします。}
X [I = 1..3] {Iの最初の4つの要素を、Jのすべての要素でスライスします}

スライスとサブスクリプトでのインデックスの命名は、パラメーターの固定シーケンスに依存するのではなく、関数呼び出しでのパラメーターの命名に似ています。スライスでインデックスに名前を付けることの利点の1つは、プログラマーが多次元配列でインデックスのシーケンスを覚えておく必要がないことです。より深い利点は、Xの次元数が変更されたときに、式を書き直さなくても自動的かつ安全に一般化できることです。

1998年:S-Lang

配列スライシングはバージョン1.0で導入されました。以前のバージョンはこの機能をサポートしていませんでした。

Aが次のような1次元配列であるとします。

    A = [1:50]; %A = [1、2、3、... 49、50]

次に、Aの最初の5つの要素の配列Bを使用して作成できます。

    B = A [[:4]];

同様に、Bは、次の方法でAの最後の5つの要素の配列に割り当てることができます。

    B = A [[-5:]];

1次元スライスの他の例は次のとおりです。

    A [-1]%Aの最後の要素
    A [*]%Aのすべての要素
    A [[:: 2]]%Aのすべての偶数要素
    A [[1 :: 2]]%Aのすべての奇数要素
    A [[-1 ::-2]]%逆順のすべての偶数要素
    A [[[0:3]、[10:14]]]%要素0-3および10-14

高次元配列のスライスも同様に機能します。

    A [-1、*]%Aの最後の行
    A [[1:5]、[2:7]]%行1〜5と列2〜7を使用する2次元配列
    A [[5:1:-1]、[2:7]]%行が逆になっていることを除いて、上記と同じ

配列インデックスは整数の配列にすることもできます。たとえば、それI = [0:9]が10個の整数の配列であるとします。次に A[I]、の最初の10個の要素の配列に相当しAます。この実際的な例は、次のような並べ替え操作です。

    I = array_sort(A); %ソートインデックスのリストを取得する
    B = A [I]; %BはAのソートされたバージョンです
    C = A [array_sort(A)]; %上記と同じですが、より簡潔です。

1999:D

配列について考えてみましょう。

int [ ]  a  =  [ 2、5、7、3、8、6、4、1 ] ; _  _ _  _ _  _ _  _ _  _ _ _  

それからスライスを取ります:

int []  b  =  a [ 2  ..  5 ];

の内容はbになります[7, 3, 8]スライスの最初のインデックスは包括的で、2番目は排他的です。

自動 c  =  a [  $ -4  .. $ -2  ] ;   

[]内の記号は配列の長さを示して いるため、動的配列cに含まれるようになったことを意味します。[8, 6]$

D配列スライスは元の配列にエイリアスされるため、次のようになります。

b [ 2 ]  =  10 ;

a内容が含まれていることを意味します[2, 5, 7, 3, 10, 6, 4, 1]エイリアスだけでなく、配列データのコピーを作成するには、次の手順を実行します。

自動 b  =  a [ 2..5  ] _  dup ;

Pythonとは異なり、Dスライスの境界は飽和しないため、このPythonコードと同等のコードはDのエラーです。

>>> d  =  [ 10、20、30 ] >>> d [ 1 5 ] [ 20、30 ] _  _ 
  

2004年:SuperCollider

プログラミング言語SuperColliderは、 J / APLのいくつかの概念を実装していますスライスは次のようになります。

a  =  [ 3、1、5、7 ] //変数に配列を割り当てますaa [  0 .. 1 ] // a最初の2つの要素を返します[ ..1] //最初の2つの要素を返しますa:ゼロは省略できますa [ 2 ..] //最後の要素まで要素3を返しますa [[ 0、3 ]] //a最初と4番目の要素を返します             
                    
                     
                     
                   

a [[ 0、3 ]] = [ 100、200 ] //a 最初と4番目の要素を置き換えますa [ 2 .. ] = [ 100、200 ] //a最後の2つの要素を置き換えます        
           


//多次元配列変数 割り当てますaa =  [ [ 0、1、2、3、4 ]  [ 5、6、7、8、9 ] [ 10、11、12、13、14 ] [ _ _ _ _ _ _ _ _ _ _ _ _ _ 15、16、17、18、19 ] ] ; _ _ _ _ _ _ _ スライス2、3 ; _                   
              //座標2と3(13を返す)のスライスを取り
ますスライスnil  3 );            //直交スライスを取得します([3、8、13、18]を返します)

2005年:

魚の配列は常に1ベースであるため、新しいスライスのインデックスは、以前のインデックスに関係なく、 1から始まります。

>  set A  seq 3  2 11        #$ Aは、値が3、5、7、9、11の配列です。
 
>  echo  $ A [( seq 2 )] #$ A35の最初の         2つの要素を出力し
ます
 
>  set B $ A [ 1 2 ]             #$ Bには、$ Aの最初と2番目の要素、つまり3、5が含まれます。
 
>  set -e A [ $ B ] ;  echo  $ A #$ Aの    3番目と5番目の要素を消去し、$Aを出力します35
 9
 

2006年:コブラ

CobraはPythonスタイルのスライスをサポートしています。リストがある場合

nums  =  [ 1、3、5、7、8、13、20 ] _  _ _  _ _  _ _  _ _  _ _  _

その場合、最初の3つの要素、中央の3つの要素、および最後の3つの要素は次のようになります。

nums [:3 ]    #等しい[1、3、5] 
nums [ 2 5 ]   等しい[5、7、8] 
nums [ -3 :] #等しい[8、13、20]  

Cobraは、「数値forループ」のスライススタイルの構文もサポートしています。

for  i  in  2   5 
    print  i 
#prints 2、3、4

for  j  in  3 
    print  j 
#prints 0、1、2

2006:WindowsPowerShell

配列はPowerShellではゼロベースであり、コンマ演算子を使用して定義できます。

PS> $ a  =  2、5、7、3、8、6、4、1 PS > # $aの最初2要素を出力ます。PS > " $ $ a [ 0、1 ] " 2 5 PS > #範囲演算子を使用してスライスを取り出します:PS> " $($ a [ 2 .. 5 ])" 7 3 8 6 PS> #最後の3つの要素を取得します:PS> " $(       

 





$ a [ -3 ..- 1 ])" 
6 4 1 
PS> #配列の内容を逆の順序で返します:
PS> " $($ a [($ a。length - 1 ).. 0  ] " #長さはSystem.Object[]のプロパティです14 6 8 3 7 5 2  

2009:移動

Goは、スライス用のPythonスタイルの構文をサポートしています(負のインデックスはサポートされていません)。配列とスライスはスライスできます。スライスがある場合

nums  =  [ ] int { 1、3、5、7、8、13、20 } _  _ _  _ _  _ _  _ _  _ 

その場合、最初の3つの要素、中央の3つの要素、最後の3つの要素、およびスライス全体のコピーは次のようになります。

nums [:3 ]   //等しい[]int {1、3、5} 
nums [ 2 5 ]  //等しい[]int {5、7、8} 
nums [ 4 :]   //等しい[]int {8 、13、20} 
nums [:]    //等しい[]int {1、3、5、7、8、13、20}

Goのスライスは参照型です。つまり、異なるスライスが同じ基になる配列を参照する場合があります。

2010:CilkPlus

Cilk Plusは、CおよびC++の拡張機能として配列スライシングの構文をサポートしています。

array_base [ lower_bound length [ stride ]] * 

CilkPlusのスライスは次のようになります。

A [ ] //すべてのベクトルAB [ 2 6 ] //ベクトルBCの要素2から7C [ ][ 5 ] //行列CDの列5D [ 0 3 2 ] //要素ベクトルDの0、2、4     
   
  
 

Cilk Plusの配列スライシングは、次の2つの点でFortranとは異なります。

  • 2番目のパラメーターは、標準Cライブラリとの一貫性を保つために、上限ではなく長さ(スライス内の要素の数)です。
  • スライスによって一時的なものが生成されることはないため、メモリを割り当てる必要はありません。割り当ては、重複しないか完全に重複する必要があります。そうでない場合、結果は未定義です。

2012:ジュリア

Julia配列スライシングMATLABのものと似ていますが、角かっこを使用します。例:

 julia > x  =  rand 4、3 4x3 Array {Float64,2}:0.323877  0.186253 0.600605 0.404664 0.894781 0.0955007 0.223562 0.18859 0.120011 0.149316 0.779823 0.0690126






julia>  x [  2 ]                 #2番目の列を取得します。
4要素配列{Float64,1}:
0.186253 
0.894781 
0.18859 
0.779823

julia>  x [ 1  ]                 #最初の行を取得します。
1x3アレイ{Float64,2}:
0.323877 0.186253 0.600605

julia>  x [ 1 2、2 3 ] #行1、2 列2、3にまたがる部分行列を取得2x2 Array {Float64,2}:0.186253 0.600605 0.894781 0.0955007             



も参照してください

参照

  1. ^ 張、江沢民; Aeron、Shuchin(2017-03-15)。「t-SVDを使用した正確なテンソル完了」信号処理に関するIEEEトランザクション電気電子技術者協会(IEEE)。65(6):1511–1526。土井10.1109/tsp.2016.2639466ISSN1053-587X _
  2. ^ ミルマン、K。ジャロッド; Aivazis、Michael(2011)。「科学者とエンジニアのためのPython」科学と工学におけるコンピューティング13(2):9–12。