这是Scala for the Impatient
提出的另一个问题
写一个返回a的函数lteqgt(values:Array [Int],v:Int) 三次包含小于v的值的计数,等于v,和 大于v。
我这样做的方式是
scala> def lteqgt(values: Array[Int], v: Int): (Int, Int, Int) = (values.count(_ < v), values.count(_ == v), values.count(_ > v))
lteqgt: (values: Array[Int], v: Int)(Int, Int, Int)
scala> lteqgt(Array(0,0,1,1,1,2,2), 1)
res47: (Int, Int, Int) = (2,3,2)
问题吗
我正在遍历数组3
次以收集计数,有没有办法在第一时间收集值?一种惯用的方式?
答案 0 :(得分:10)
这是使用foldLeft
的完美案例。它将完全遍历您的集合一次,而不创建另一个集合(如groupBy
所做的那样),并且与更通用的aggregate
相比更简洁。
def lteqgt(values: Array[Int], v: Int): (Int, Int, Int) =
values.foldLeft((0, 0, 0)) {
case ((lt, eq, gt), el) =>
if (el < v) (lt + 1, eq, gt)
else if (el == v) (lt, eq + 1, gt)
else (lt, eq, gt + 1)
}
如果你想要达到最高效率,同时避免使用命令式方法,那么尾递归是可行的方法:
def lteqgt(values: Array[Int], v: Int): (Int, Int, Int) = {
def rec(i:Int, lt:Int, eq:Int, gt:Int):(Int, Int, Int) =
if (i == values.length) (lt, eq, gt)
else if (values(i) < v) rec(i + 1, lt + 1, eq, gt)
else if (values(i) == v) rec(i + 1, lt, eq + 1, gt)
else rec(i + 1, lt, eq, gt + 1)
rec(0, 0, 0, 0)
}
这避免了每次迭代时构造Tuple
和盒装Ints。如果你感兴趣的话,整个事情会编译为java while
中的 //url string
NSString *ImageURL = @"yoururl";
//string to data conversion
NSData *imagedata = [NSData dataWithContentsOfURL:[NSURL URLWithString:ImageURL]];
//set image
imageView.image = [UIImage imageWithData:imageData];
循环。
答案 1 :(得分:2)
虽然功能性解决方案可以说更优雅,但不要忘记&#34;无聊&#34;但有效的必要解决方案。
def lteqgt(values: Array[Int], v: Int): (Int, Int, Int) = {
var lt = 0
var eq = 0
var gt = 0
values.foreach (i => {
if (i<v) lt += 1
else if (i==v) eq += 1
else gt += 1
})
(lt,eq,gt)
}
以上可能会为每个循环生成一个函数调用,正如Aivean在下面指出的那样。为了提高效率,我们可以手动移除封盖。 (遗憾的是,编译器尚未完成此类优化)
def lteqgt(values: Array[Int], v: Int): (Int, Int, Int) = {
var lt = 0
var eq = 0
var gt = 0
var i = 0
while (i < values.length) {
if (values(i) < v ) lt += 1
else if (values(i) == v) eq += 1
else gt += 1
i += 1
}
(lt,eq,gt)
}
答案 2 :(得分:0)
与@ chi相似,但让我们超过设计规格,以便我们可以比较Ints以外的其他数据。标题是&#34; Traversing&#34;所以让我们使用Traversable,这样我们就可以分析所有其他集合。机器可能不会更快地执行此操作,但它可能是程序员时间效率。
def lteqgt[T](values:Traversable[T], v:T)(implicit cmp: Ordering[T]):(Int,Int,Int) = {
var l = 0;
var e = 0;
var g = 0;
for(x <- values){
if (cmp.equiv(v,x)) e += 1
else if (cmp.gt(x,v)) g += 1
else l += 1
}
(l,e,g);
};
用法:
scala> lteqgt(List(1.0,2.0,3.0,2.5), 2.5)
res0: (Int, Int, Int) = (2,1,1)
scala> lteqgt(Array(1.0,2.0,3.0,2.5), 2.5)
res1: (Int, Int, Int) = (2,1,1)
scala> lteqgt(Vector(1.0,2.0,3.0,2.5), 2.5)
res2: (Int, Int, Int) = (2,1,1)
scala> lteqgt(Set(1.0,2.0,3.0,2.5), 2.5)
res3: (Int, Int, Int) = (2,1,1)
scala> lteqgt(1 to 100, 45)
res4: (Int, Int, Int) = (44,1,55)
scala> lteqgt(Range(0,100,3), 50)
res5: (Int, Int, Int) = (17,0,17)
scala> lteqgt(List("fee","fie","foe","fum"), "foo")
res6: (Int, Int, Int) = (3,0,1)
scala> lteqgt(None, 1)
res7: (Int, Int, Int) = (0,0,0)
scala> lteqgt(Some(2), 1)
res8: (Int, Int, Int) = (0,0,1)