You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Groovy中集合减法如何仅单次扣除元素以保留重复项?

问题分析与解决方案

为什么原代码得到空列表?

Groovy里List的-操作符(对应minus()方法)的行为和你预期的不一样——它会移除左边列表中所有出现在右边列表里的元素,不管该元素在左边出现多少次。

看你的代码执行后:

  • l1最终是 [0, 0, 1, 1, 2, 2, 3, 3, 4, 4](每个数字被添加了两次)
  • l2是 [0, 1, 2, 3, 4](每个数字出现一次)

执行l1 - l2时,会把l1里所有的0、1、2、3、4全部移除,所以结果自然是空列表。

实现“每个元素仅扣除一次”的解决方案

如果你想让l2中的每个元素只从l1里移除一次,可以手动遍历l2,逐个从l1的副本中移除第一个匹配的元素(避免修改原列表):

def l1 = [] as List; def l2 = [] as List; 
for(int i = 0; i < 5; i++) { 
    l1 << i; l2 << i; l1 << i; 
} 
println(l1); // 输出: [0, 0, 1, 1, 2, 2, 3, 3, 4, 4]
println(l2); // 输出: [0, 1, 2, 3, 4]

// 创建l1的副本,避免修改原列表
def result = new ArrayList<>(l1)
// 遍历l2的每个元素,从副本中移除一次
l2.each { element ->
    result.remove(element) // 只移除第一个匹配到的元素
}
println(result); // 输出: [0, 1, 2, 3, 4]

另一种灵活方式:基于元素计数构建结果

如果l2中元素可能存在重复,或者需要更精细的次数控制,可以先统计l1中每个元素的出现次数,再减去l2中对应的次数,最后重新构建列表:

def countMap = l1.countBy { it } // 统计每个元素的出现次数: [0:2, 1:2, 2:2, 3:2, 4:2]
l2.each { element ->
    if (countMap[element] > 0) {
        countMap[element]-- // 每个元素次数减1
    }
}
// 根据剩余次数构建结果列表
def result = countMap.flatMap { key, count -> [key] * count }
println(result); // 输出: [0, 1, 2, 3, 4]

总结

Groovy默认的-操作符是全量匹配移除,若需要按“每个元素仅移除一次”的逻辑处理,需要手动实现遍历移除或基于计数的方式,而不能直接依赖默认的minus操作。

内容的提问来源于stack exchange,提问作者xunitc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:43:30