List 缺少值的列表上的算术运算
我试图在一个可能包含缺失值的列表上做一些算术运算。 到目前为止,我用选项[Int]表示我的列表:List 缺少值的列表上的算术运算,list,scala,math,missing-data,List,Scala,Math,Missing Data,我试图在一个可能包含缺失值的列表上做一些算术运算。 到目前为止,我用选项[Int]表示我的列表: val mylist=List( Option(4), Option(8), None ) 通过这种表示,我可以轻松地在列表上应用函数(例如,乘以2): 然而,这看起来比它需要的更复杂,所以我想知道我是否遗漏了什么 而且,我也不知道如何写出像总和这样的东西。我想应该可以用一个(大的)reduce表达式 因此,我想知道: List[Option[Int]]是此用例的良好表示 mylist.map(
val mylist=List( Option(4), Option(8), None )
通过这种表示,我可以轻松地在列表上应用函数(例如,乘以2):
然而,这看起来比它需要的更复杂,所以我想知道我是否遗漏了什么
而且,我也不知道如何写出像总和这样的东西。我想应该可以用一个(大的)reduce表达式
因此,我想知道:
- List[Option[Int]]是此用例的良好表示
是映射的最佳方式mylist.map(*2))
- 有一种简单的求和方法吗
选项是合适的。但是列表
可能不是。在列表中
位置通常不是你应该依赖的,因为它不是随机访问。也许向量
会更好,或者您需要想出一种更好的方法来建模您的问题,也就是说,不要将其作为缺少值的列表
您可以使用for表达式很好地处理选项
:
for (o <- mylist; x <- o) yield x * 2
总而言之:
mylist.flatten.sum
- List[Option[Int]]是此用例的良好表示
是否可以使用flatMap更早地将其展平?例如,如果您正在使用map创建此列表,则可以使用flatMap,并且不会缺少值。我的建议是,如果可能,甚至不要表示缺失的值。若您需要表示它们,那个么这个选项是理想的
mylist.map(*2))
是映射的最佳方式
- 有一种简单的求和方法吗
嵌套映射可能更可取。您还可以foldLeft
foldLeft
如果您需要做除求和/积之外的事情,它也很有用
scala> val mylist=List( Option(4), Option(8), None )
mylist: List[Option[Int]] = List(Some(4), Some(8), None)
scala> mylist.foldLeft(0){
| case (acc, Some(i)) => acc + i
| case (acc, _) => acc
| }
res7: Int = 12
scala> (0 /: mylist) {
| case (acc, Some(i)) => acc + i
| case (acc, _) => acc
| }
res8: Int = 12
scala> (0 /: mylist) {
| case (acc, Some(i)) => acc - (i * 2)
| case (acc, _) => acc
| }
res16: Int = -24
因此,我想知道:
List[Option[Int]]是此用例的良好表示
选项绝对是表示缺失值的首选方式。您还可以考虑将其更改为列表[(Int,Int)]
,其中第一个元素表示原始列表中的位置,第二个元素表示值
mylist.map(*2))
是映射的最佳方式
在我看来,没有更短或更简洁的方式来表达这一点。(您有两个“级别”,这就是为什么您需要两个映射!)使用我建议的数据结构,这将变成mylist.map(t=>(t._1,t._2*2))
有一种简单的求和方法吗
没有比om nom建议的更简单的方法了。对于我的数据结构,它将是mylist.map(u._2).sum
实现这一点的最通用和最简洁的方法是使用的半群类型类。这样,您就不局限于List[Option[Int]]
,而是可以将相同的函数应用于List[Int]
import scalaz._
import Scalaz._
object S {
def double[A:Semigroup](l:List[A]) = l.map(x => x |+| x)
def sum[A:Semigroup](l:List[A]) = l.reduce(_ |+| _)
def main(a:Array[String]) {
val l = List(Some(1), None, Some(2))
val l2 = List(1,2)
println(double(l))
println(sum(l))
println(double(l2))
println(sum(l2))
}
}
这张照片
List(Some(2), None, Some(4))
Some(3)
List(2, 4)
3
我不确定你想达到什么目的,但这似乎不是正确的方法。如果您需要确定“列表”中是否存在某个值,那么设置
可能更适合您的需要:
scala> val s = Set(4,8)
s: scala.collection.immutable.Set[Int] = Set(4, 8)
scala> s(4)
res0: Boolean = true
scala> s(5)
res1: Boolean = false
scala> s map (_ * 2)
res2: scala.collection.immutable.Set[Int] = Set(8, 16)
scala> s reduceLeft((a,b) => a+b)
res3: Int = 12
甚至更简单:
scala> s sum
res4: Int = 12
如果您需要更复杂的内容,并且列表中元素的索引很重要,您可以使用映射
,其中键模拟索引,缺少的值可以映射到某个默认值:
scala> val m = Map(1 -> 4, 2 -> 8) withDefault(n => 0)
m: scala.collection.immutable.Map[Int,Int] = Map(1 -> 4, 2 -> 8)
scala> m(1)
res5: Int = 4
scala> m(3)
res6: Int = 0
scala> m map {case (k,v) => (k,2*v)}
res7: scala.collection.immutable.Map[Int,Int] = Map(1 -> 8, 2 -> 16)
scala> m.foldLeft(0){case (sum,(_,v)) => sum+v}
res8: Int = 12
同样,我不确定你的需求是什么,但感觉你走错了方向……
选项
是一种我在使用前会三思而后行的类型。问问自己这是否真的有必要。可能有一些解决方案可以以更优雅的方式实现您正在尝试的目标。要求和值,您可以使用mylist.Flatte.sum
将所有值都否决answers@drstevens发生的事情reported@drstevens我很好奇,为什么会有人这么做?(除非他们否决了所有答案,只有自己的答案除外?@Stevens博士,这很奇怪。我确实在这里投了赞成票,但我从来没有投过反对票,是的,理解和扁平化并没有持续下去,看起来@scala_新手想要拯救他们。如果没有,还有一种方法:flatMap them:mylist.flatMap(*2)
实际上@om nom nom,flatMap不起作用(我有同样的想法),因为函数的参数类型必须是Option[Int]
,在我的用例中,我有一系列对象。我需要对这些对象的属性进行统计,但是这些对象缺少(不同的)属性。我不确定我会如何使用这里的那些技术使用映射[YourObjects,List[Attributes]]
怎么样?我不确定我是否理解你的建议。如果没有选项,如何将属性存储在列表中?如果你建议只保留现有属性的列表,我该如何区分它们(它们的索引不会固定)?我建议只保留现有属性的列表。假设您有一个属性trait:MyAttribute
,那么,对于每个需要的属性,您都可以将该trait扩展为实际值。比如:SomeAttribute或者,如果属性非常简单,并且创建一个超级特征是一个“过度解决方案”,那么您可以使用:Map[YourObject,Map[Int,Attribute]]
scala> s sum
res4: Int = 12
scala> val m = Map(1 -> 4, 2 -> 8) withDefault(n => 0)
m: scala.collection.immutable.Map[Int,Int] = Map(1 -> 4, 2 -> 8)
scala> m(1)
res5: Int = 4
scala> m(3)
res6: Int = 0
scala> m map {case (k,v) => (k,2*v)}
res7: scala.collection.immutable.Map[Int,Int] = Map(1 -> 8, 2 -> 16)
scala> m.foldLeft(0){case (sum,(_,v)) => sum+v}
res8: Int = 12