Scalaのリストにあるアイテムを取得しますか?


205

スカラのリストから、インデックスiの要素だけを世界でどのように取得しますか?

私が試したところget(i)[i]何もうまくいきませんでした。グーグルは、リスト内の要素を「見つける」方法のみを返します。しかし、私はすでに要素のインデックスを知っています!

コンパイルしないコードは次のとおりです。

def buildTree(data: List[Data2D]):Node ={
  if(data.length == 1){
      var point:Data2D = data[0]  //Nope - does not work

  }
  return null
}

リストapiを見ても、目が交差するだけでは役に立ちません。


1
まあ、それはdata.headがうまくいったようです...しかし、それでも私には最初の要素しか与えられず、リストの誰も与えません。
Andriy Drozdyuk、2011

インデックスが範囲外でないことが確実な場合は、Seqトレイトのapply(index)を使用してください。scala-lang.org/api/current/...
Beezer

data.drop(i).headはi番目の要素にアクセスするために機能します
Vinay

@Vinayこれはコストのかかる操作です。したがって、「drop(i).head」は避けてください。
Shubham Agrawal 2017

回答:


305

括弧を使用:

data(2)

ただし、リンクされたリストはトラバースするのに時間がかかるため、リストを使用してそれを頻繁に実行することは望ましくありません。コレクションにインデックスを付ける場合は、Vector(不変)またはArrayBuffer(ミュータブル)を使用するか、またはArray(これは単なるJava配列ですが、の(i)代わりにでインデックスを作成する場合を除きます[i])。


1
基本的に私はJavaのArrayListのようなものを探しています。不変でも大丈夫だと思います。
Andriy Drozdyuk

1
ArrayBufferのように動作しArrayListます。 Vector不変のようにArrayList機能します-読み取ることはできますが、新しいものを作成しないと書き込みはできません。
レックスカー

subListはどうですか?たとえば、Javaでは「data.subList(0、index)」を実行します。
Andriy Drozdyuk、2011

気にしないで、私はそれを得ました-それは「スライス」です!ArrayBufferをベクターに変換できますか?または、メソッドから返すことができるより一般的なタイプはありますか?たとえば、JavaではListインターフェースを返します。
Andriy Drozdyuk、2011

1
あなたは、変換することができますArrayBufferIndexedSeq使用しました.toIndexedSeqIndexedSeqより一般的なタイプです。(この場合、実際にはVector。として実装されるIndexedSeqことがわかります。) は、インデックスを付けるのに適したコレクションのスーパータイプです。また、できることにも注意してくださいVector() ++ myArrayBuffer。これは、ほぼすべてのコレクション(どちらの側でも)で機能します。 ++指定した2つから新しいコレクションを作成し、左側のタイプを保持します。 Vector()空のベクトルなので、必要なものが生成されます。
レックスカー

121

より安全な方法を使用liftすると、存在する場合は値を抽出し、存在しない場合は正常に失敗します。

data.lift(2)

これは、リストがその要素を提供するのに十分な長さでない場合はNoneを返し、そうである場合はSome(value)を返します。

scala> val l = List("a", "b", "c")
scala> l.lift(1)
Some("b")
scala> l.lift(5)
None

この方法で失敗する可能性のある操作を実行しているときはいつでも、オプションを使用して型システムを取得し、要素が存在しないケースを処理していることを確認してください。

説明:

これが機能するのは、リストapply(たとえば、かっこだけを使用するl(index))が、リストに要素がある場合に定義される部分関数のようなものだからです。このList.liftメソッドは、apply基本的に結果をOptionでラップすることにより、部分関数(一部の入力に対してのみ定義される関数)を通常の関数(任意の入力に対して定義される)に変換します。


11
リフトが綺麗です。配列のサイズをチェックせずに、arrayIndexOutOfBoundエラーを回避できます。–
Naveen Sachar

9

なぜ括弧なのか?

これはScalaでのプログラミングの本からの引用です。

この例で示されているもう1つの重要なアイデアは、Scalaで配列が括弧でアクセスされる理由を理解するのに役立ちます。ScalaはJavaよりも特殊なケースが少ない。配列は、Scalaの他のクラスと同様に、単にクラスのインスタンスです。変数に1つ以上の値を囲む括弧を適用すると、Scalaはコードをその変数に対してapplyという名前のメソッドの呼び出しに変換します。したがって、greetStrings(i)はgreetStrings.apply(i)に変換されます。したがって、Scalaで配列の要素にアクセスすることは、他のメソッド呼び出しと同じです。この原理は配列に限定されません。括弧内のいくつかの引数へのオブジェクトの適用は、applyメソッド呼び出しに変換されます。もちろん、これは、そのタイプのオブジェクトが実際に適用メソッドを定義している場合にのみコンパイルされます。したがって、これは特別なケースではありません。原則です。

関数型プログラミングスタイルを使用して特定の要素(この場合は最初の要素)をプルする方法の例をいくつか示します。

  // Create a multdimension Array 
  scala> val a = Array.ofDim[String](2, 3)
  a: Array[Array[String]] = Array(Array(null, null, null), Array(null, null, null))
  scala> a(0) = Array("1","2","3")
  scala> a(1) = Array("4", "5", "6")
  scala> a
  Array[Array[String]] = Array(Array(1, 2, 3), Array(4, 5, 6))

  // 1. paratheses
  scala> a.map(_(0))
  Array[String] = Array(1, 4)
  // 2. apply
  scala> a.map(_.apply(0))
  Array[String] = Array(1, 4)
  // 3. function literal
  scala> a.map(a => a(0))
  Array[String] = Array(1, 4)
  // 4. lift
  scala> a.map(_.lift(0))
  Array[Option[String]] = Array(Some(1), Some(4))
  // 5. head or last 
  scala> a.map(_.head)
  Array[String] = Array(1, 4)


0

これは、最近のインデックスを介してリストのデータにアクセスするための推奨される方法です。

scala> val list = List("a","b","c")
scala> list.get(1)
Some("b")
scala> list.get(5)
None

しかし、上記のRex Kerrのように:インデックスを使用している場合は、リストの代わりにベクターを使用することを検討する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.