Scala - 使用int列表作为填充新数据结构的索引

时间:2015-01-03 22:20:56

标签: list scala dictionary indexing

我有一个对象列表(在本例中为Items),它们有类别ID和属性(它本身就是自定义类型列表)。

我正在尝试修改一个带有整数列表的函数,例如List(101, 102, 102, 103, 104)对应于项目的类别ID,并创建包含类别类型(这是一个选项)的元组列表,以及与每个类别一起出现的属性列表中的每个属性类型。到目前为止,我有以下内容,但我收到value _2 is not a member of Product with Serializable

的错误
def idxToData(index: List[Int], items: Seq[Item]): List[(Option[Category], Property[_])] = {

  def getId(ic: Option[Category]): Int => {
   ic match {
     case Some(e) => e._id
     case None => 0
    }
  }

  index.flatMap(t => items.map(i => if(t == getId(i.category)){
    (i.category, i.properties.list.map(_.property).toList.sortWith(_._id < _._id))
  } else {
    None
  }.filter(_ != None )
  ))
   .map(x => x._2.map(d => (x._1, d)))
   .toList
}

我不确定它是如何分配该类型的(我假设我应该有一个我想要映射的元组列表)。

总的来说,scala是否有更好的方法来获取索引列表所需的结果,并使用它来访问列表中的特定项目,其中每个相应项目的两个部分的元组将“替换” index用于创建新的列表结构?

2 个答案:

答案 0 :(得分:3)

你应该拆分代码,为事物命名(添加一些val和一些defs),当编译器不同意你的时候,编写类型,这样编译器会尽早告诉你它不同意的地方(不要担心,我们都是从FP开始时做的那样

此外,在发布此类问题时,您可能希望提供已引用但未定义的元素接口(的相关部分)。什么是“是”(是项目?),项目,类别,属性......,或简化您的代码,以便它们不会出现。

现在,问题是:

if(t == (i.category match { case Some(e) => e._id})){
   (i.category, i.properties.list.map(_.property).toList.sortWith(_._id < _._id))
} else {
  None
}

第一个分支是类型Tuple2(Int,无论如何),而第二个分支是完全不相关的类型None。显然,没有比AnyRef更好的常见超类型,因此这是if表达式的类型。然后is.map的类型(假设is是某种Seq)将是Seq [AnyRef]。过滤器不会更改类型,因此仍然Seq[AnyRef],而map(x =>...)x也是AnyRef,而不是Tuple2,所以它没有_2

当然,列表实际上只包含元组,因为最初它有元组和Nones,你已经删除了Nones。但是当它输入AnyRef时,编译器就输了。 (正如编译器错误消息所述,并且正如Imm所指出的,编译器发现的类型比AnyRef Product with Serializable更精确;但是,这对你没有任何好处,所有有用的输入信息仍然在那里失去了)。

要保留类型,通常应该执行

之类的操作
if(....) {
   Some(stuff)
else
   None

那将是键入的选项[类型的东西],其中的东西类型是你的对。

然而,常规收集更简单。 它有点像匹配,除了它采用部分函数,​​并且它丢弃未定义部分函数的元素。

那就是

is.collect { case i if categoryId(i) == Some(t) => 
   (i.catetory, i.properties....)
}

假设您已定义

def categoryId(item: Item): Option[Int] = item.category.map(._id)

答案 1 :(得分:1)

执行此操作时:

is.map(i => if(t == getId(i.category)){
  (i.category, i.properties.list.map(_.property).toList.sortWith(_._id < _._id))
} else {
  None
}

你得到一个List[Product with Serializable](你应该得到的是一个类型错误,但这可能是一个很长的题外话),因为它是None和{{1}的唯一超类型或者那个元组类型是什么。编译器不够智能,无法携带联合类型,并且当你(Category, List[Property[_]])列表中剩下的任何内容必须是元组时,

尝试改写这一部分。例如。您可以在filter(_ != None)之前is.filter(i => t == getId(i.category)) 首先,然后您就不需要在列表中使用map了。