Scala - 使用整数列表作为索引来填充新的数据结构
Scala - using a list of ints as an index to populate a new data structure
我有一个对象列表(在本例中为项目),其中包含类别 ID 和属性(它本身是自定义类型的列表)。
我正在尝试定义一个接受整数列表的函数,例如List(101, 102, 102, 103, 104)
对应于 Items 的类别 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 中是否有更好的方法来实现期望的结果,即获取索引列表并使用它来访问列表中的特定项目,其中每个对应项目的两个部分的元组 "replace" 创建新列表结构的索引?
你应该拆分你的代码,给事物命名(添加一些 vals 和一些 defs),当编译器不同意你的时候,写类型,这样编译器会及早告诉你它不同意的地方(不要别担心,从 FP 开始我们都这样做了)
此外,在发布此类问题时,您可能希望给出(的相关部分)被引用但未定义的元素的接口。什么是"is"(那是items?),Item,category,properties.....,或者简化你的代码,让它们不出现。
现在,问题来了:
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]。 filter 不改变类型,所以仍然是 Seq[AnyRef]
,而在 map(x =>...)
中,x
也是一个 AnyRef
,而不是 Tuple2
,所以它没有_2
。
当然,这个列表实际上只包含元组,因为它原来有元组和无,而你去掉了无。但是当编译器输入 AnyRef
时,它就丢失了。
(正如编译器错误消息和 Imm 所指出的那样,编译器找到了比 AnyRef
、Product with Serializable
稍微更精确的类型;但是,这对您没有任何好处,所有有用的类型信息仍然迷失在那里)。
要保留类型,通常你应该做一些事情,比如
if(....) {
Some(stuff)
else
None
可以输入选项[类型],其中类型是您的配对。
但是,例程收集有一些更简单的东西。
它有点像 match,只是它采用偏函数,并丢弃未定义偏函数的元素。
那就是
is.collect { case i if categoryId(i) == Some(t) =>
(i.catetory, i.properties....)
}
假设你已经定义了
def categoryId(item: Item): Option[Int] = item.category.map(._id)
当你这样做时:
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
和 (Category, List[Property[_]])
的唯一超类型或任何元组类型。编译器不够聪明,无法执行联合类型并弄清楚当你 filter(_ != None)
列表中剩下的任何东西都必须是元组。
尝试改写这部分。例如。你可以在 map
之前先 is.filter(i => t == getId(i.category))
,然后你就不需要在你的列表中弄乱 None
。
我有一个对象列表(在本例中为项目),其中包含类别 ID 和属性(它本身是自定义类型的列表)。
我正在尝试定义一个接受整数列表的函数,例如List(101, 102, 102, 103, 104)
对应于 Items 的类别 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 中是否有更好的方法来实现期望的结果,即获取索引列表并使用它来访问列表中的特定项目,其中每个对应项目的两个部分的元组 "replace" 创建新列表结构的索引?
你应该拆分你的代码,给事物命名(添加一些 vals 和一些 defs),当编译器不同意你的时候,写类型,这样编译器会及早告诉你它不同意的地方(不要别担心,从 FP 开始我们都这样做了)
此外,在发布此类问题时,您可能希望给出(的相关部分)被引用但未定义的元素的接口。什么是"is"(那是items?),Item,category,properties.....,或者简化你的代码,让它们不出现。
现在,问题来了:
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]。 filter 不改变类型,所以仍然是 Seq[AnyRef]
,而在 map(x =>...)
中,x
也是一个 AnyRef
,而不是 Tuple2
,所以它没有_2
。
当然,这个列表实际上只包含元组,因为它原来有元组和无,而你去掉了无。但是当编译器输入 AnyRef
时,它就丢失了。
(正如编译器错误消息和 Imm 所指出的那样,编译器找到了比 AnyRef
、Product with Serializable
稍微更精确的类型;但是,这对您没有任何好处,所有有用的类型信息仍然迷失在那里)。
要保留类型,通常你应该做一些事情,比如
if(....) {
Some(stuff)
else
None
可以输入选项[类型],其中类型是您的配对。
但是,例程收集有一些更简单的东西。 它有点像 match,只是它采用偏函数,并丢弃未定义偏函数的元素。
那就是
is.collect { case i if categoryId(i) == Some(t) =>
(i.catetory, i.properties....)
}
假设你已经定义了
def categoryId(item: Item): Option[Int] = item.category.map(._id)
当你这样做时:
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
和 (Category, List[Property[_]])
的唯一超类型或任何元组类型。编译器不够聪明,无法执行联合类型并弄清楚当你 filter(_ != None)
列表中剩下的任何东西都必须是元组。
尝试改写这部分。例如。你可以在 map
之前先 is.filter(i => t == getId(i.category))
,然后你就不需要在你的列表中弄乱 None
。