https://kotlinlang.org logo
Title
d

Daniel

11/22/2018, 3:15 PM
Hello and a big thanks in advance! I need advice from kotlin collection specialists 🙂 Is there an more elegant way to extract two elements out of a list which are equal given a predicate? I came up with this:
object TwoLikelyVariablesMatcher : CondensingMatcher {
    override fun matches(operands: Terms): Boolean {
        operands.filterIsInstance<AnyVariable>()
                .groupBy { it.unsignedName }
                .forEach { (_, variablesWithSameName) ->
                    if(variablesWithSameName.size > 1) return true
                }

        return false
    }

    override fun matches(source: Terms, target: Terms): Boolean {
        TODO("not implemented")
    }
}

@Test
    fun `A two likely variables matcher matches with operands containing exactly two likely variables`() {
        // GIVEN
        val operands = termsOf(
                PositiveVariable("x"),
                mock(),
                PositiveVariable("y"),
                mock(),
                NegativeVariable("x"))

        // THEN
        assertTrue(TwoLikelyVariablesMatcher.matches(operands))
    }

    @Test
    fun `A two likely variables matcher doesn't match with operands containing zero likely variables`() {
        // GIVEN
        val operands = termsOf(
                PositiveVariable("x"),
                PositiveVariable("y"),
                PositiveVariable("z"))

        // THEN
        assertFalse(TwoLikelyVariablesMatcher.matches(operands))
    }
What it does is the following: I have a list of mathematical terms and I want to filter out two variables which have the same unsigned Name (for example
x
or
y
.
t

Timmy

11/22/2018, 6:58 PM
For the matches function you can replace the
.foreach
and `return`s with
.any
[1]. Do you also want a function that returns the duplicates, or only detect them? [1] https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/any.html
d

Daniel

11/23/2018, 5:36 PM
Thank you for the suggestion with any! For the question, I actually need both. I incorporatet your hint into it and changed the extraction a bit:
override fun matches(operands: Terms) = operands.asSequence()
            .filterIsInstance<AnyVariable>()
            .groupBy { it.unsignedName }
            .any { it.value.size > 1 }

override fun extract(operands: Terms): Pair<Terms, Terms> {
        val firstLikelyVariables = operands.asSequence()
                .filterIsInstance<AnyVariable>()
                .groupBy { it.unsignedName }
                .filterValues { it.size > 1 }
                .values
                .first()

        val source = termsOf(firstLikelyVariables.first)
        val target = termsOf(firstLikelyVariables.second)

        return source and target
    }
👍 1