在Scala列表中获取项目?


205

您究竟如何从scala的List中获得索引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
}

看着List api并没有帮助,因为我的眼睛只是交叉。


1
好吧,似乎data.head起作用了……但是,这只是给我第一个要素,而不是列表中的任何一个要素。
2011年

如果您确定索引没有超出范围,请使用Seq特质apply(index)scala-lang.org/api/current/…–
Beezer

data.drop(i).head用于访问第i个元素
Vinay

@Vinay这是一项昂贵的操作。因此,应避免使用“ drop(i).head”。
Shubham Agrawal

Answers:


305

使用括号:

data(2)

但是,您实际上并不想经常使用列表,因为链接列表需要时间来遍历。如果要索引到集合中,请使用Vector(不可变的)或ArrayBuffer(可变的)或可能的Array(这只是一个Java数组,除非再次使用(i)而不是对其进行索引[i])。


1
基本上,我在寻找类似ArrayList的东西。我想不可变也可以。
2011年

1
ArrayBufferArrayListVector就像一个不可变的东西ArrayList-您可以阅读,但是如果不创建一个新的就不能写作。
Rex Kerr

子列表怎么样?例如在Java中,我执行“ data.subList(0,index)”。
Andriy Drozdyuk

没关系,我明白了-是“切片”!我可以将ArrayBuffer转换为Vector吗?还是我可以从方法中返回更通用的类型?例如,在Java中,我将返回List接口。
2011年

1
您可以转换ArrayBufferIndexedSequsing .toIndexedSeqIndexedSeq是更通用的类型。(在这种情况下,它实际上被实现为Vector。) IndexedSeq是可以索引到的合理的collection的超类型。另外,请注意,您可以这样做Vector() ++ myArrayBuffer,这几乎适用于任何集合(在任一侧)。 ++从您指定的两个集合中构建一个新集合,并保留左侧集合的类型。 Vector()是空向量,因此它将产生您想要的。
Rex Kerr

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

每当执行可能以这种方式失败的操作时,最好使用Option并获取类型系统以确保您正在处理元素不存在的情况。

说明:

之所以apply可行,是因为List的列表(例如,加到括号中的糖l(index))就像一个在列表中有元素的地方定义的部分函数。通过将结果基本包装在Option中,该List.lift方法将部分apply功能(仅为某些输入定义的功能)转换为普通功能(为任何输入定义的功能)。


11
电梯很漂亮。我能避免arrayIndexOutOfBound错误,不检查数组的大小..
纳文萨查尔

9

为什么加上括号?

这是scala编程书籍的引文。

该示例说明的另一个重要思想将使您了解为何在Scala中使用括号访问数组。Scala的特殊情况比Java少。数组只是类的实例,与Scala中的其他任何类一样。当对一个或多个值使用圆括号括起变量时,Scala会将代码转换为对该变量调用名为apply的方法的调用。因此,greetStrings(i)转换为greetStrings.apply(i)。因此,在Scala中访问数组的元素只是像其他任何方法调用一样。该原理不限于数组:对象对括号中某些参数的任何应用都将转换为apply方法调用。当然,仅当该类型的对象实际定义了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一样:如果使用索引,则应考虑使用Vector而不是List。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.