Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 计算所有值或停止并返回最佳值(如果找到)_List_Scala_Map_Stream - Fatal编程技术网

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

我有一个项目列表,我为每个项目计算一个值。计算这个值有点计算密集,所以我希望尽可能地最小化它

我需要实现的算法是:

  • 我有一个值X

  • 每一项

    a。计算它的值,如果它小于0,则完全忽略它

    b。如果(值>0)和(值
  • 返回列表中的所有(项、值)对(值大于0),理想情况下按值排序

  • 更清楚地说,只有当所有项的值都不小于X时,才会执行第3步。在第2步中,当我们遇到第一个小于X的项时,我们不应该计算其余项,而只返回该项(显然,我们可以将其自身返回到Set()中,以匹配返回类型)

    我现时的守则如下:

      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返回项目