List 计算所有值或停止并返回最佳值(如果找到)
我有一个项目列表,我为每个项目计算一个值。计算这个值有点计算密集,所以我希望尽可能地最小化它 我需要实现的算法是:List 计算所有值或停止并返回最佳值(如果找到),list,scala,map,stream,List,Scala,Map,Stream,我有一个项目列表,我为每个项目计算一个值。计算这个值有点计算密集,所以我希望尽可能地最小化它 我需要实现的算法是: 我有一个值X 每一项 a。计算它的值,如果它小于0,则完全忽略它 b。如果(值>0)和(值 val值=计算值(项目) 如果(值>=0)//我们过滤掉负的 映射+(键->值) 其他的 地图 } val bestItem=itemValMap.minBy(u._2) if(最佳项目._2i->computeValue(i)}.filter(u.\u 2>=0) weighteditem
val itemValMap = items.foldLeft(Map[Item, Int)]()) {
(map : Map[Item, Int], key : Item) =>
val value = computeValue(item)
if ( value >= 0 ) //we filter out negative ones
map + (key -> value)
else
map
}
val bestItem = itemValMap.minBy(_._2)
if (bestItem._2 < bestX)
{
List(bestItem)
}
else
{
itemValMap.toList.sortBy(_._2)
}
val itemmap=items.foldLeft(Map[Item,Int)]()){
(map:map[Item,Int],key:Item)=>
val值=计算值(项目)
如果(值>=0)//我们过滤掉负的
映射+(键->值)
其他的
地图
}
val bestItem=itemValMap.minBy(u._2)
if(最佳项目._2<最佳项目)
{
列表(最佳项目)
}
其他的
{
itemValMap.toList.sortBy(u.u 2)
}
然而,这段代码所做的是计算列表中的所有值并选择最佳值,而不是在找到“更好”值时停止。我怀疑我必须以某种方式使用流来实现这一点?好的,我不确定您的整个设置是什么样子的,但我试图准备一个能够反映您的情况的最小示例 这就是:
object StreamTest {
case class Item(value : Int)
def createItems() = List(Item(0),Item(3),Item(30),Item(8),Item(8),Item(4),Item(54),Item(-1),Item(23),Item(131))
def computeValue(i : Item) = { Thread.sleep(3000); i.value * 2 - 2 }
def process(minValue : Int)(items : Seq[Item]) = {
val stream = Stream(items: _*).map(item => item -> computeValue(item)).filter(tuple => tuple._2 >= 0)
stream.find(tuple => tuple._2 < minValue).map(List(_)).getOrElse(stream.sortBy(_._2).toList)
}
}
给出:
[info] Running Main
Original: Item(3) , calculated: 4
Original: Item(4) , calculated: 6
Original: Item(8) , calculated: 14
Original: Item(8) , calculated: 14
Original: Item(23) , calculated: 44
Original: Item(30) , calculated: 58
Original: Item(54) , calculated: 106
Original: Item(131) , calculated: 260
[success] Total time: 31 s, completed 2013-11-21 15:57:54
因为没有小于2的值,所以我们得到了一个按计算值排序的列表。请注意,缺少两对,因为计算值小于0并已过滤掉
好的,现在让我们尝试一个不同的最小截止点:
val result = StreamTest.process(5)(items)
其中:
[info] Running Main
Original: Item(3) , calculated: 4
[success] Total time: 7 s, completed 2013-11-21 15:55:20
很好,它返回一个只有一项的列表,第一个值(原始列表中的第二项)小于“最小”值,不小于0。
我希望上面的示例能够很容易地适应您的需要…好的,我不确定您的整个设置是什么样子的,但我试图准备一个能够反映您的情况的最小示例 这就是:
object StreamTest {
case class Item(value : Int)
def createItems() = List(Item(0),Item(3),Item(30),Item(8),Item(8),Item(4),Item(54),Item(-1),Item(23),Item(131))
def computeValue(i : Item) = { Thread.sleep(3000); i.value * 2 - 2 }
def process(minValue : Int)(items : Seq[Item]) = {
val stream = Stream(items: _*).map(item => item -> computeValue(item)).filter(tuple => tuple._2 >= 0)
stream.find(tuple => tuple._2 < minValue).map(List(_)).getOrElse(stream.sortBy(_._2).toList)
}
}
给出:
[info] Running Main
Original: Item(3) , calculated: 4
Original: Item(4) , calculated: 6
Original: Item(8) , calculated: 14
Original: Item(8) , calculated: 14
Original: Item(23) , calculated: 44
Original: Item(30) , calculated: 58
Original: Item(54) , calculated: 106
Original: Item(131) , calculated: 260
[success] Total time: 31 s, completed 2013-11-21 15:57:54
因为没有小于2的值,所以我们得到了一个按计算值排序的列表。请注意,缺少两对,因为计算值小于0并已过滤掉
好的,现在让我们尝试一个不同的最小截止点:
val result = StreamTest.process(5)(items)
其中:
[info] Running Main
Original: Item(3) , calculated: 4
[success] Total time: 7 s, completed 2013-11-21 15:55:20
很好,它返回一个只有一项的列表,第一个值(原始列表中的第二项)小于“最小”值,不小于0。
我希望上面的例子可以很容易地适应您的需要…避免计算不需要的值的一个简单方法是使用
查看方法使您的收集变得懒惰:
val weigthedItems = items.view.map{ i => i -> computeValue(i) }.filter(_._2 >= 0 )
weigthedItems.find(_._2 < X).map(List(_)).getOrElse(weigthedItems.sortBy(_._2))
val weigtheditions=items.view.map{i=>i->computeValue(i)}.filter(u.\u 2>=0)
weighteditems.find(u._2
通过示例,这里是REPL中的一个测试:
scala> :paste
// Entering paste mode (ctrl-D to finish)
type Item = String
def computeValue( item: Item ): Int = {
println("Computing " + item)
item.toInt
}
val items = List[Item]("13", "1", "5", "-7", "12", "3", "-1", "15")
val X = 10
val weigthedItems = items.view.map{ i => i -> computeValue(i) }.filter(_._2 >= 0 )
weigthedItems.find(_._2 < X).map(List(_)).getOrElse(weigthedItems.sortBy(_._2))
// Exiting paste mode, now interpreting.
Computing 13
Computing 1
defined type alias Item
computeValue: (item: Item)Int
items: List[String] = List(13, 1, 5, -7, 12, 3, -1, 15)
X: Int = 10
weigthedItems: scala.collection.SeqView[(String, Int),Seq[_]] = SeqViewM(...)
res27: Seq[(String, Int)] = List((1,1))
scala>:粘贴
//进入粘贴模式(按ctrl-D键完成)
类型项=字符串
def计算值(项:项):Int={
println(“计算”+项目)
item.toInt
}
val项目=列表[项目](“13”、“1”、“5”、“7”、“12”、“3”、“1”、“15”)
val X=10
val weigthedItems=items.view.map{i=>i->computeValue(i)}.filter(U2>=0)
weighteditems.find(u._2
正如您所看到的,computeValue只在第一个值1
)时调用。避免计算不需要的值的一个简单方法是使用视图
方法使集合变懒:
val weigthedItems = items.view.map{ i => i -> computeValue(i) }.filter(_._2 >= 0 )
weigthedItems.find(_._2 < X).map(List(_)).getOrElse(weigthedItems.sortBy(_._2))
val weigtheditions=items.view.map{i=>i->computeValue(i)}.filter(u.\u 2>=0)
weighteditems.find(u._2
通过示例,这里是REPL中的一个测试:
scala> :paste
// Entering paste mode (ctrl-D to finish)
type Item = String
def computeValue( item: Item ): Int = {
println("Computing " + item)
item.toInt
}
val items = List[Item]("13", "1", "5", "-7", "12", "3", "-1", "15")
val X = 10
val weigthedItems = items.view.map{ i => i -> computeValue(i) }.filter(_._2 >= 0 )
weigthedItems.find(_._2 < X).map(List(_)).getOrElse(weigthedItems.sortBy(_._2))
// Exiting paste mode, now interpreting.
Computing 13
Computing 1
defined type alias Item
computeValue: (item: Item)Int
items: List[String] = List(13, 1, 5, -7, 12, 3, -1, 15)
X: Int = 10
weigthedItems: scala.collection.SeqView[(String, Int),Seq[_]] = SeqViewM(...)
res27: Seq[(String, Int)] = List((1,1))
scala>:粘贴
//进入粘贴模式(按ctrl-D键完成)
类型项=字符串
def计算值(项:项):Int={
println(“计算”+项目)
item.toInt
}
val项目=列表[项目](“13”、“1”、“5”、“7”、“12”、“3”、“1”、“15”)
val X=10
val weigthedItems=items.view.map{i=>i->computeValue(i)}.filter(U2>=0)
weighteditems.find(u._2
正如您所看到的,computeValue只在第一个值1
)调用。谢谢您的回复。在我的原始代码中,我使用了foldLeft
而不是filter
,以避免创建两次集合,一次使用所有项,然后使用第二次使用筛选项,因为我可能有很多项<0
,这两种情况下我都不需要。视图是否对过滤器执行相同的操作?您还可以解释一下getOrElse
部分吗?不确定为什么在weightedItems.sortBy(\uu.\u 2)
中使用weightedItems
,它没有从值<0的项中筛选出来,或者是?我希望始终使用va返回项目