我刚开始学习Scala。我想通过循环添加数字,并希望找出最小数字。所以,我做了这个
for(j<-0 until numberOfQuery){
val z = readLine.split(" ");
var from = Integer.parseInt(z(0));
var to = Integer.parseInt(z(1));
var i=from;
var getNumber = List[Int](to+1);
var counter = 0;
for(i <-from until to+1){
getNumber.apply(storeElemets(i));
System.out.println(storeElemets(i));
}
System.out.println(getNumber.min);
}
对于输入10 20 30 40 11 22 33 44 15 5
和0 5
,最小数量为10
。但是,它返回java.lang.IndexOutOfBoundsException
。所以,
1)在Scala中声明List
的正确方法是什么?
2)我的错误是什么?添加数字的正确方法是什么。
答案 0 :(得分:3)
List
是一个不可变的single linked list。
使用List[Int](i)
创建一个包含单个元素(i
)的列表:
List(5)
//res0: List[Int] = List(5)
实际上你正在调用工厂方法List.apply
。请参阅object List
documentation。
您应该使用Nil
作为空列表:
var getNumber: List[Int] = Nil
// or
var getNumber = List.empty[Int]
使用getNumber.apply(n)
(或getNumber(n)
),您尝试按列表中的索引选择元素。见List
documentation。因此,您IndexOutOfBoundsException
与n > getNumber.size
一起获得了::
。
您可以使用getNumber = storeElemets(i) :: getNumber
// with syntax sugar:
getNumber ::= storeElemets(i)
方法将元素添加到列表中,如下所示:
List
请注意from to to
是不可变的 - 您只能创建一个新列表。
您可以使用from until to+1
代替to
。方法until
(和map
)创建Range
。您可以在任何scala集合(包括Range
)上使用方法val getNumber = (from until to).map{i => storeElemets(i)}
// with for-comprehensions:
val getNumber =
for {
i <- from until to
} yield storeElemets(i)
,如下所示:
map
请注意,Range
上的IndexedSeq
会创建List
而不是List
。在此示例中,您不需要List
,但如果您需要List
,则可以使用方法toList
将集合转换为val myList = getNumber.toList
:
{{1}}
答案 1 :(得分:2)
您可以使用List(10, 20, 30, 40, 11, 22, 33, 44, 15, 5)
声明您的列表。您可以通过附加到它的方法.toList
从任何集合构建列表。
你的第一个错误是你没有创建一个大小为+ 1的列表,它只是创建一个列表,其中包含一个+ 1的元素。请尝试List.fill(to+1)(0)
将列表填充为+ 1个零。
此外,忘记使用分号并使用val
代替var
,以确保不变性,这对于高规模程序非常方便。
storeElemets
未定义,但如果它返回i
,则在第二次迭代时,索引对于单例列表getNumber
来说太高了
如果输入如下:
0 5 10 20 30 40 11 22 33 44 15 5 a b
其中a和b是考虑列表的下部和上部索引,那么您应该执行以下操作:
val z = readLine.split(" ")
val from = z(0).toInt
val to = z(1).toInt
val getNumber = z.toList.drop(2).drop(from).take(to-from+1)
val sum = getNumber.sum // Equivalent to getNumber.foldLeft(0){ case (res, n) => res + n }
println(sum)
println(getNumber.min)
答案 2 :(得分:1)
如果您真的需要,可以使用构建器:
val b = List.newBuilder[Int] // creates a list builder
for(i <-from until to+1){
b += storeElemets(i) // stores an element
println(storeElemets(i))
}
b.result() // you need to call it to retrieve a collection from builder
P.S。没有必要(甚至不建议在scala样式指南中)在行尾使用;
。此外,您可以在没有类定义的情况下调用println
。
答案 3 :(得分:1)
除了人们已经注意到的其他问题之外(可变性与不变性,分号,不知道storeElemets
做了什么等等)你还选择了一些模糊和困难的价值名称,这些名称与常见术语和帮助有冲突使这段代码难以阅读。
在行之间阅读,看起来storeElemets
就是你所谓的“输入”
我的看法是这样的:
val storeElemets = IndexedSeq(10,20,30,40,11,22,33,44,15,5) //immutable
for(qry <- 0 until numberOfQuery) {
val elems = readLne split " " //split into an array
val Array(start, end) = elems take 2 map (_.toInt) //pattern matching
val stored = (start to end) map storeElemets //also immutable
//alternatively, this is more efficient in *most* cases...
val stored = storeElemets drop start take (end-start+1)
//println is a *side effect*, so we want to isolate it from the other logic
stored foreach println
println(stored.min)
}
答案 4 :(得分:0)
考虑
for(j<-0 until numberOfQuery){
val lineSum = readLine.split(" ").map { _.toInt }.sum
println(s"lineSum = $lineSum")
}
对于每个字符串行读取,按空格拆分字符串,将每个拆分项解析为整数,最后汇总所有整数值并打印结果。
答案 5 :(得分:0)
比初学者要高一点,我会尽力回答您的问题:
1)在Scala中声明列表的正确方法是什么?
有一些正确的方法,例如:
val numberList = List(10,20,30,40,11,22,...)
val数字列表= 10 :: 20 :: 30 :: 40 :: ... ::无
2)我的错误是什么?
您应该注意,scala在某些方面与其他编程语言完全不同。一方面是您不应该使用var(变量),而只能使用val。 这是因为在scala中,您可以并行执行操作,而这不能通过变量来完成(或者至少非常困难)。 因此,使用scala的一个非常重要的意义是:
不要使用变量(除非绝对必要)!
事实证明,大多数时候不需要变量。但是要进行无变量编程,必须从头开始学习一些东西(至少这是我的经验)。 因此,val(值)是一个不变的对象,一旦定义它就无法更改。对于List对象也是如此。 这意味着,一旦您定义了列表对象numbersList,则使用:
val numberList = List(10,20,30,40,11,22,...)
您无法更改它,这就是您应该在Scala中工作的方式。 您可以更改numbersList中的一项,但是随后您将获得一个完整的新List,结果仅更改了一项。 结果,您也不应该使用循环(因为循环需要计数器变量)。 而且,与vars一起使用的for-construkt并不是循环,而是一个表达式,该表达式被转换为带有map,flatMap和filter的表达式(并且可以并行运行)
3)什么是加号的正确方法?
对于给定的List对象numbersList,它只是上面的
val结果= numbersList.sum
由于概念上的差异,我认为当您了解一种或几种计算机语言并尝试将您对这种语言的知识转移到scala时,很难学习scala。
建议我推荐免费的在线课程:scala的发明者Martin Odersky教授提供的“ scala中的函数式编程原理”。
当然,任何人都可以按照他想要的方式使用计算机语言,但是有时最好了解某种语言的使用方式,以充分利用语言。