多个distinctBy不会给出一致的结果

时间:2018-07-20 14:30:30

标签: kotlin

我有一个字符串列表,我正在尝试保留唯一的字符串,并忽略字母大小写和空格

例如:import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows class MyTests { @Test fun `division by zero -- should throw ArithmeticException`() { assertThrows<ArithmeticException> { 1 / 0 } } } => listOf("a", "A", "A ", "B")

所以我尝试了此解决方案:

listOf("a", "B")
  

输出:list = [a,A,B]

但是当我更改val list = listOf("a", "A", "A ", "B") .distinctBy { it.toLowerCase() } .distinctBy { it.trim() } println("list = ${list}") 的顺序时,它出奇地起作用:

distinctBy
  

输出:list = [a,B]

我希望输出为第二个,但是为什么第一个代码不起作用?

当我更改项目的顺序时,我遇到了同样的问题:

val list = listOf("a", "A", "A  ", "B")
        .distinctBy { it.trim() }
        .distinctBy { it.toLowerCase() }

println("list = ${list}")
  

输出:list = [a,A,B]

3 个答案:

答案 0 :(得分:3)

distinctBy不会更改列表的内容,而是使用给定的转换函数比较列表中的每个条目,然后返回一个新列表。

因此,即使aA在您的第一个定义中是不同的,它们也只会返回找到的第一个匹配项(在本例中为a)。 您的第一个非重复字符后的列表包含以下项:

[a, A  , B]

下一个distinct接受这些元素,并通过修剪内容进行比较,这基本上会导致相同的结果,因为所有内容都是基于第二个distinct转换函数的distinct。

您可能想做的事情是这样的:

listOf("a", "A", "A  ", "B")
   .distinctBy { it.toLowerCase().trim() }

实际上结合了两个转换函数并导致:

[a, B]

或者,您可以执行以下操作:

listOf("a", "A", "A  ", "B")
    .map(String::toLowerCase)
    .map(String::trim)
    .distinct()
    .also(::println)

然后返回:

[a, b]

或者,如果您真的在乎收到的输入是什么:

listOf("a", "A", "A  ", "B")
    .groupBy { it.toLowerCase().trim() }
    .let(::println)

返回:

{a=[a, A, A  ], b=[B]}

从这里您可以获取一个或全部〜real输入,例如您可以再次添加.map { it.value[0] }来返回任何组的第一个〜real匹配项。

答案 1 :(得分:1)

val list =  listOf("a", "A ", "A", "A ", "B")
        .map { it -> it.trim() }
        .distinctBy { it.toLowerCase() }

因为第一次修整,然后询问不同的值
如果您首先获得不同的值,则结果为list = [a, A , B]
所以修剪后给出:list = [a, A, B]

distinctBy意味着获得所有不同的(不同的)物品

答案 2 :(得分:1)

在第一种情况下,当您应用.distinctBy { it.toLowerCase() }时,它将比较["a", "a", "a ", "b" ]的值,结果数组将为["a", "A ", "B"]

调用.distinctBy { it.trim() }时,它将比较"a", "A", "B"个字符串,得到["a", "A ", "B"]

在第二种情况下,应用.distinctBy { it.trim() }后,您得到["a", "A", "B"],然后.distinctBy { it.toLowerCase() }将比较["a","a","b"],并得到理想的结果

您还可以将两个操作合并在一个 distinctBy 块中:

val list = listOf("a", "A", "A ", "B") .distinctBy { it.toLowerCase().trim() }