【问题标题】:Finding values greater than * in a map list在地图列表中查找大于 * 的值
【发布时间】:2016-11-15 07:40:08
【问题描述】:

我当前的系统是一个映射的 String,List[Int],String 是一个键值,“Sk1”,“Sk2”等,而 int 是一个从 0-9 的数字列表。

这是我当前查找所有列表的方法,如何编辑它以仅查找所有大于所选“SK*”的“Sk*”。列表的值是尾部的最后一个元素,我已经有一个函数要查找。它是handleFive 选项菜单。为了澄清,我需要找到最后一个元素(已经有那个功能)然后只显示大于所选股票的股票。

菜单选项处理程序

  def handleFive(): Boolean = {
    mnuShowSingleDataStock(currentStockLevel)
    true
  }

  def handleSeven(): Boolean = {
    mnuShowPointsForStock(allStockLevel)
    true
  }

调用用户并与用户交互的函数

// Returns a single result, not a list
  def mnuShowSingleDataStock(f: (String) => (String,Int)) = {
    print("Stock > ")
    val data = f(readLine)
    println(s"${data._1}: ${data._2}")
  }

//Returns a list value
  def mnuShowPointsForStock(f: (String) => (String,List[Int])) = {
    print("Stock > ")
    val data = f(readLine)
    println(s"${data._1}: ${data._2}")
  }

不确定如何编辑,目前它显示列表中的所有值,我只想返回大于所选值的值

  //Show last element in the list, most current
  def currentStockLevel (stock: String): (String, Int) = {
    (stock, mapdata.get (stock).map(findLast(_)).getOrElse(0))
  }

//Unsure how to change this to only return values greater than the selected one, not everything
  def currentStockLevel (stock: String): (String, List[Int]) = {
    (stock, mapdata.get (stock).map(findLast(_)).getOrElse(0))
  }

我当前的映射列表 - 这是 MAPDATA

val mapdata = Map(
    "SK1" -> List(9, 7, 2, 0, 7, 3, 7, 9, 1, 2, 8, 1, 9, 6, 5, 3, 2, 2, 7, 2, 8, 5, 4, 5, 1, 6, 5, 2, 4, 1),
    "SK2" -> List(0, 7, 6, 3, 3, 3, 1, 6, 9, 2, 9, 7, 8, 7, 3, 6, 3, 5, 5, 2, 9, 7, 3, 4, 6, 3, 4, 3, 4, 1),
    "SK3" -> List(8, 7, 1, 8, 0, 5, 8, 3, 5, 9, 7, 5, 4, 7, 9, 8, 1, 4, 6, 5, 6, 6, 3, 6, 8, 8, 7, 4, 0, 6),
    "SK4" -> List(2, 9, 5, 7, 0, 8, 6, 6, 7, 9, 0, 1, 3, 1, 6, 0, 0, 1, 3, 8, 5, 4, 0, 9, 7, 1, 4, 5, 2, 8),
    "SK5" -> List(2, 6, 8, 0, 3, 5, 5, 2, 5, 9, 4, 5, 3, 5, 7, 8, 8, 2, 5, 9, 3, 8, 6, 7, 8, 7, 4, 1, 2, 3),
    "SK6" -> List(2, 7, 5, 9, 1, 9, 8, 4, 1, 7, 3, 7, 0, 8, 4, 5, 9, 2, 4, 4, 8, 7, 9, 2, 2, 7, 9, 1, 6, 9),
    "SK7" -> List(6, 9, 5, 0, 0, 0, 0, 5, 8, 3, 8, 7, 1, 9, 6, 1, 5, 3, 4, 7, 9, 5, 5, 9, 1, 4, 4, 0, 2, 0),
    "SK8" -> List(2, 8, 8, 3, 1, 1, 0, 8, 5, 9, 0, 3, 1, 6, 8, 7, 9, 6, 7, 7, 0, 9, 5, 2, 5, 0, 2, 1, 8, 6),
    "SK9" -> List(7, 1, 8, 8, 4, 4, 2, 2, 7, 4, 0, 6, 9, 5, 5, 4, 9, 1, 8, 6, 3, 4, 8, 2, 7, 9, 7, 2, 6, 6)
  )

【问题讨论】:

  • @CyrilleCorpet 我已经更新了这个问题,也许让它更容易理解?如果你不介意再看一眼
  • 如果您的库存是SK3,您是要获取SK4、SK5 ...到SK9中每一个的最后一个元素,还是SK3中所有值大于最后一个元素的元素?跨度>
  • 如果我选择 SK3,我希望 SK4、SK5 等的所有最后一个元素的最后一个值都高于 SK3 @CyrilleCorpet 的最后一个值
  • 您是否还想要 SK1 和 SK2 的最后一个值(如果它们更大)?它对代码没有太大的改变,但我只是确保我理解了这个问题。
  • 是的,每一个更大的 SK 和数字,所以如果我搜索 SK1 会得到 SK2 > 9、SK3>8 等

标签: scala list search


【解决方案1】:

Map[String, List[Int]] 类型有一个filterKeys(f: String => Boolean) 方法,以便只保留满足给定谓词的键。

一个可能的解决方案是

// get int value from stock if of the form "SK<int>"
def stockInt(stock: String): Option[Int] = 
  Try(stock.drop(2).toInt).filter(_ => stock.startsWith("SK")).toOption

// we keep the keys in the return, so that you do not get unordered results
// (order is not assured by Map)
def currentStockLevel(stock: String): (String, Map[String, Int]) = {
  val maybeN = stockInt(stock)
  def isGreater(other: String) = (for {
    o <- stockInt(other)
    n <- maybeN
  } yield o > n).getOrElse(true) // if any key is not in the form of SK*, assume it is greater than the original stock

  (
    stock, 
    mapdata.filterKeys(isGreater(_)).mapValues(findLast(_))
  )
}

如果您确定只有“SK”键,另一种可能性是使用SortedMap,它使用SortedSet 作为其键,这样您就可以确保键值对按您的需要排序他们是。

在这种情况下,解决方案将是

//put all values in mapdata in a SortedMap
val sortedMap = SortedMap[String, List[Int]]() ++ mapdata

def currentStockLevel(stock: String): (String, List[Int]) = {
  (
    stock, 
    sortedMap.dropWhile(_ <= stock).toList.map(_._2).map(findLast(_))
  )
}

编辑(在 cmets 关于预期回报之后):

如果我很了解您要做什么,您希望过滤值而不是键。这不是问题,Map 也有一个 filter(p: ((K, V)) =&gt; Boolean): Map[K, V] 方法可以做到这一点:

def currentHigherStockLevel(stock: String): Map[String, Int] = {
  val current = datamap.get(stock).map(findLast).getOrElse(0) // if stock is not in the keySet, we keep all keys, by keeping those greater than 0.
  datamap.mapValues(findLast).filter {
    case (sk, val) => val > current
  }
}  

这会返回一个Map[String; Int],其中的值是最后一个大于作为参数给出的值(我们保留它们的键,因为它们可能有用)。

【讨论】:

  • 我当前的系统允许我搜索,比如“SK1”,并使用提供的代码返回列表中的最后一项,在本例中为“1”,因此“SK1 > 1”就是回来。我需要能够搜索“SK1”,而不是返回最后一个值,而是返回所有其他列表中大于我搜索的所有其他最后一个值
【解决方案2】:

如果密钥字符串是 "SK9""SK10" 之类的东西,那么您必须删除数字,转换为 Int,然后比较/过滤它们,但如果您的密钥保持完全一致的格式: "SK001", "SK002" ... "SK009", "SK010" ... "SK099", "SK100" 等,然后您使用简单的字符串比较来过滤您想要的内容。

mapdata.filterKeys(_ >= stock).values  // an Iterable[List[Int]]

【讨论】:

  • 我在尝试使用此方法时收到错误“无法解析符号“filterKeys””,知道为什么吗?
  • filterKeys 是mapdata 上的方法,而不是mapdata.get(stock) 上的方法,Option[List[Int]]
  • 抱歉,我将建议的过滤器插入了错误的位置。我不清楚您如何处理/返回多个结果,但这是过滤它们的方法。
  • @jwvh 对不起,我想我问错了,例如,我搜索“SK2”,结果是列表中的最后一个 int,即“1”所以我的回报会是“SK2 > 1”
猜你喜欢
  • 1970-01-01
  • 2012-03-11
  • 1970-01-01
  • 1970-01-01
  • 2018-06-21
  • 1970-01-01
  • 1970-01-01
  • 2021-12-17
  • 1970-01-01
相关资源
最近更新 更多