组合多个谓词不起作用
Posted
技术标签:
【中文标题】组合多个谓词不起作用【英文标题】:Combining multiple predicates not working 【发布时间】:2022-01-06 06:23:41 【问题描述】:我正在尝试从列表中过滤掉某些项目,并以特定顺序将它们合并到最终列表中。第一个代码 sn-p 似乎效率低下,因为它创建了 2 个用于过滤的列表然后迭代它们但是该代码有效。第二个 sn-p 试图结合这两个过滤但是 map 运算符没有将项目添加到 otherNums 列表中
有人可以帮我理解为什么会这样吗?
片段 1:
fun main()
val favItem = 0
val list = listOf(11, 12, 13, 2,3,4,5,6,7,10, favItem)
val greaterThan10 = list.filteritem -> item > 10
val otherNums = list.asSequence().filteritem -> item != favItem.filteritem -> item < 10
println(" $greaterThan10") //the list is filled with proper numbers
println("merged list $greaterThan10.plus(favItem).plus(otherNums)")
结果:
[11, 12, 13]
merged list [11, 12, 13, 0, 2, 3, 4, 5, 6, 7]
片段 2:
fun main()
val favItem = 0
val list = listOf(11, 12, 13, 2,3,4,5,6,7,10, favItem)
val greaterThan10 = mutableListOf<Int>()
val otherNums = list.asSequence().filteritem -> item != favItem.map
if(it > 10)
greaterThan10.add(it)
it
.filteritem -> item != 10
println("$greaterThan10") // the list is empty
println("merged list $greaterThan10.plus(favItem).plus(otherNums)")
结果:
[]
merged list [0, 11, 12, 13, 2, 3, 4, 5, 6, 7]
【问题讨论】:
您需要greaterThan10
列表还是只需要最后一个?
不知道为什么,但删除 asSequence()
使得 greaterThan10
至少被填满
@JoãoDias 我需要最后一个,但greaterThan10
列表通过检查greaterThan10
中是否有正确的值来帮助调试
@IvoBeckers asSequence
有助于避免为每个 filter
创建 2 个单独的列表。效率更高一点
是的,我明白了。但由于某种原因,如果你把它排除在外,大于 10 确实会被填满。而且我不明白为什么,因为在这两种情况下,greaterThan10.add(it)
在打印之前都会被调用
【参考方案1】:
在您的第二个 sn-p 中,greaterThan10
列表是空的,因为序列的惰性行为,仅当遇到诸如 toList()
或 sum()
之类的终端操作时才会迭代序列。
在您的情况下,当您编写 .plus(otherNums)
时,序列会被迭代。 List
+ Sequence
产生List
。如果您在打印合并列表后打印您的greaterThan10
列表,您会发现它已被填充。
顺便说一句,这里不需要Sequence
。序列比列表更高效的两种主要情况是:
map
、filter
等。
使用Iterable
会创建很多中间Iterable
s,它们会消耗更多内存,
当您在末尾进行某种短路操作时,例如 take()
、contains()
、first()
等,即不需要迭代整个集合即可获得最终结果。
根据文档,
序列的惰性增加了一些开销,这在处理较小的集合或进行更简单的计算时可能很重要。因此,您应该同时考虑 Sequence 和 Iterable 并决定哪一个更适合您的情况。
对于最终的解决方案,我认为您可以使用您的 sn-p 1。这对我来说看起来不错,只需删除不必要的 asSequence
并将两个 filter
合并为一个。
fun main()
val favItem = 0
val list = listOf(11, 12, 13, 2, 3, 4, 5, 6, 7, 10, favItem)
val greaterThan10 = list.filter item -> item > 10
val otherNums = list.filter it != favItem && it <= 10
println(" $greaterThan10")
println("merged list $greaterThan10 + favItem + otherNums")
我认为在列表中使用filter
比minus
更好,因为后者具有二次最坏情况时间复杂度(如果我没记错的话)。
我写了一个小例子来展示差异。运行this 几次,看看有什么不同。
另外,正如@IvoBeckers 在评论中提到的, “如果原始列表没有 favItem,此方法也会添加一个。如果列表有多个 favItem,此方法将用一个替换它。”
【讨论】:
也许值得一提:如果原始列表没有 favItem 这个方法也会添加一个。而且我相信如果列表有多个 favItem 这个方法会用一个替换它。 是的,你是对的。感谢您指出。将此添加到答案中。【参考方案2】:val favItem = 0
val list = listOf(11, 12, 13, 2, 3, 4, 5, 6, 7, 10, favItem)
val greaterThan10 = list.filter it > 10
val otherNums = list - greaterThan10.toSet() - favItem
println("greaterThan10: $greaterThan10") // [11, 12, 13]
println("otherNums: $otherNums") // [2, 3, 4, 5, 6, 7, 10]
println("merged list: $greaterThan10 + favItem + otherNums")
编辑:将 .minus(...) 替换为 -。感谢@Ivo Beckers 的评论。
【讨论】:
我认为list.minus((greaterThan10 + favItem).toSet())
比需要的更复杂。我相信一个简单的val otherNums = list - greaterThan10 - favItem
也一样好
已编辑。非常感谢您的建议。更容易捕捉。【参考方案3】:
val favItem = 0
val list = listOf(11, 12, 13, 2, 3, 4, 5, 6, 7, 10, favItem)
val (greaterThan10, otherNums) = list // destructuring assignment
.filter it != favItem // filter out favItem
.groupBy it > 10 // create two groups
.toSortedMap o1, _ -> if (o1) -1 else 1 // sort groups in the order [true, false]
.map it.value.toList() // return the two lists
println("greaterThan10: $greaterThan10")
println("otherNums: $otherNums")
println("merged list: $greaterThan10 + favItem + otherNums")
【讨论】:
以上是关于组合多个谓词不起作用的主要内容,如果未能解决你的问题,请参考以下文章
ffmpeg:组合/合并多个 mp4 视频不起作用,输出仅包含第一个视频