【问题标题】:How to filter a list of tuples in scala?如何过滤scala中的元组列表?
【发布时间】:2012-10-18 19:33:31
【问题描述】:

我在 Scala 中有以下列表,我想根据一个条件进行过滤,这样如果有任何具有重复第一个值的元组, 就像下面的例子一样,我想排除

List((a,1), (a,2)) 

因为它有“a”作为重复。

【问题讨论】:

  • 您要删除两个术语((a,1)和(a,2))还是只删除一个(过滤另一个)?那一个 List((a,1), (a,2), (b,1), (b,2)) 会产生一个空的 List,对吧?
  • 至少尽量不要让它看起来像 Coursera Progfun 课程

标签: scala filter tuples scala-collections


【解决方案1】:

您想过滤您的result 使用一个只保留那些没有重复“键”的列表的功能

result filter noDuplicateKeys

此过滤函数必须采用对列表List[(A,B)],并且仅当对第一个元素不存在于所有元素的其他地方时才返回true,并且可以实现为

def noDuplicateKeys[A, B](xs: List[(A, B)]) = 
    (xs groupBy (_._1)).values forall {_.size < 2}

它将元素分组为一个Map,其键是As,其值是与该键配对的Bs 的对应列表。

根据这个值,您只能接受大小不超过 1 的值

【讨论】:

  • cool .. 我在考虑同样的问题,但无法理解 scala ,需要获取所有键,将它们组合在一起并检查是否有任何计数 ._1)).values forall {.size
  • 您能解释一下(_._1).values_.size 的工作原理吗? _. 的使用真的让我很困惑。在我看来,在某些情况下,它有助于避免提及明显的事情,例如......如果我按最小年龄过滤人类列表,我会说类似humans.filter(_.age &gt; 18),因为该列表只会有人类,并且我认为它也使它更具多态性,例如,如果一个列表有人类的其他东西,但我仍然想使用相同的标准进行过滤。也许我错了,但我仍然不明白你的答案代码中发生了什么。
  • @newbie 在这种情况下为_._1,它是函数文字的简写语法,也就是匿名函数。这意味着您在不给它命名的情况下动态定义一个函数。一般来说,扩展的语法是x =&gt; x._1,你可以像这样将它传递给groupBy方法:xs.groupBy(x =&gt; x._1)。 groupBy 方法需要一个函数作为参数,我们给它一个参数。由于这个函数字面量只使用一个参数一次,我们可以避免使用_ 占位符给它命名,所以x =&gt; x._1 等价于_._1
  • @newbie 你可以了解更多here
  • @newbie 好吧,_ 的许多用途让所有人都感到困惑,这是可以理解的,尤其是因为在 haskell 中,您不需要任何占位符来编写无点样式或咖喱函数。 .
【解决方案2】:

我相信下面的代码会做你想做的事(只删除第一对,对吧?):

我正在使用模式匹配来执行此操作,如果您想过滤所有内容,您可以对您的列表进行递归或执行 Kyle 建议的操作。看看这个:

val a = "a"                                      
val b = "b"                                     

var result =
    List(
      List(),
      List((a, 1), (a, 2)),
      List((a, 1), (b, 1)),
      List((a, 1), (b, 2)),
      List((a, 2), (b, 1)),
      List((a, 2), (b, 2)),
      List((b, 1), (b, 2)),
      List((a, 1), (a, 2), (b, 1)),
      List((a, 1), (a, 2), (b, 2)),
      List((a, 1), (b, 1), (b, 2)),
      List((a, 2), (b, 1), (b, 2)),
      List((a, 1), (a, 2), (b, 1), (b, 2))) 

val filteredResult = (for (list <- result)
    yield list match {
    case x :: y :: xys if (x._1 == y._1) =>  xys
    case _ => list
  }).distinct

结果:

//> List()
//| List((a,1), (b,1))
//| List((a,1), (b,2))
//| List((a,2), (b,1))
//| List((a,2), (b,2))
//| List((b,1))
//| List((b,2))
//| List((a,1), (b,1), (b,2))
//| List((a,2), (b,1), (b,2))
//| List((b,1), (b,2))

distinct 只会过滤生成的空列表。

干杯!

【讨论】:

  • 我认为这不对,您正在比较前两个元素并保留列表的其余部分。如果匹配在第二个和第三个元素之间怎么办?
  • 嗯,这就是我从 Shakti 的问题中了解到的。我知道他的问题来自哪里(Coursera ProgFun),是的,你必须通过整个列表来完成,在这种情况下,我的答案是不正确的。但是,关于他的问题,我相信这是相当准确的。干杯!
【解决方案3】:

我认为这是从List[List[Tuple2[Char, Int]]] 中过滤掉列表中的元素具有相同元素的项目。在这种情况下,列表的一个元素是List[Tuple2[Char, Int]],当元素相同时,我想返回一个Boolean。这个List[Tuple2[Char, Int]] 被映射到Tuple 的第一个元素,然后使用distinct 和size 将逻辑应用于新的字符列表,以检查元素是否相同并保留那些只有一个元素的元素。

过滤器

filter(xs => xs.map(ys => ys._1).distinct.size != 1 || xs.size == 1)

测试数据:

scala> val a = List(List(('a',1)))
a: List[List[(Char, Int)]] = List(List((a,1)))

scala> val aa = List(List(('a',1),('a',1)))
aa: List[List[(Char, Int)]] = List(List((a,1), (a,1)))

scala> val ab = List(List(('a',1),('b',1)))
ab: List[List[(Char, Int)]] = List(List((a,1), (b,1)))

scala> val aba = List(List(('a',1),('b',1),('a',1)))
aba: List[List[(Char, Int)]] = List(List((a,1), (b,1), (a,1)))

测试用例。

scala> a.filter(xs => xs.map(ys => ys._1).distinct.size != 1 || xs.size == 1)
res34: List[List[(Char, Int)]] = List(List((a,1)))

scala> aa.filter(xs => xs.map(ys => ys._1).distinct.size != 1 || xs.size == 1)
res35: List[List[(Char, Int)]] = List()

scala> ab.filter(xs => xs.map(ys => ys._1).distinct.size != 1 || xs.size == 1)
res36: List[List[(Char, Int)]] = List(List((a,1), (b,1)))

scala> aba.filter(xs => xs.map(ys => ys._1).distinct.size != 1 || xs.size == 1)
res37: List[List[(Char, Int)]] = List(List((a,1), (b,1), (a,1)))

【讨论】:

    【解决方案4】:

    基于@pagoda_5b 解决方案,我认为我们可以找到更好的解决方案。

    你怎么看:

    def noDuplicateKeys(l: List[(Char, Int)]): Boolean = l.toMap.size == l.size
    
    list filter noDuplicateKeys
    

    ;)

    【讨论】:

      猜你喜欢
      • 2011-05-27
      • 2016-11-15
      • 1970-01-01
      • 1970-01-01
      • 2023-01-27
      • 2016-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多