Skip to content

util: handle duplicate elements in Collection.containsExactlyInAnyOrder()#6318

Merged
westnordost merged 3 commits into
streetcomplete:masterfrom
RubenKelevra:fix_collection_contains_exactly_in_any_order
Aug 13, 2025
Merged

util: handle duplicate elements in Collection.containsExactlyInAnyOrder()#6318
westnordost merged 3 commits into
streetcomplete:masterfrom
RubenKelevra:fix_collection_contains_exactly_in_any_order

Conversation

@RubenKelevra

@RubenKelevra RubenKelevra commented Jun 6, 2025

Copy link
Copy Markdown
Contributor

containsAll() only checked for unique element presence, not frequencies. Changed to use count maps for duplicate element comparison.

The original implementation would incorrectly return true for collections
like [1, 2, 2, 3] and [1, 2, 3, 3] because:

  • Both have the same size (4)
  • Both contain the elements 1, 2, and 3

The new implementation uses groupingBy().eachCount() to create frequency maps ({1=1, 2=2, 3=1} vs {1=1, 2=1, 3=2}), which correctly identifies these collections as different due to varying element frequencies.

This ensures the function behaves as its name suggests - checking for exact content equality regardless of order.

…er()

containsAll() only checked for unique element presence, not frequencies.
Changed to use count maps for duplicate element comparison.
@westnordost

westnordost commented Jun 6, 2025

Copy link
Copy Markdown
Member

Right, thank you!

That reminds me, I wanted to get rid of this function. IIRC it is only used in tests, for things like

assertTrue(
  actualResult.containsExactlyInAnyOrder(expectedResult)
)

while I'd rather use this

assertEquals(
  expectedResult.toSet(),
  actualResult.toSet()
)

I use this at a few places already.

Why is it better? Because if it fails, I get a better feedback error message from the unit test.

And yeah, I realize now that it has the same issue as the current implementation of that function... hmm... 🤔

So maybe we just need a new function

assertEqualsInAnyOrder(
  expectedResult,
  actualResult
)

...which uses your implementation but will print a useful error when the test fails.

@RubenKelevra

Copy link
Copy Markdown
Contributor Author

That reminds me, I wanted to get rid of this function. IIRC it is only used in tests, for things like

Yeah I was curious if that's even an issue, so I searched for uses before I changed it. But there were uses in the codebase as well in app/src/commonMain/kotlin/de/westnordost/streetcomplete/data/osm/edits/create/CreateNodeFromVertexAction.kt.

That's also the reason I've chosen this more per formant variant which should run at O(n) space, O(n) time so it works for large data lists as well.

@RubenKelevra RubenKelevra marked this pull request as draft June 7, 2025 05:24
@RubenKelevra

Copy link
Copy Markdown
Contributor Author

Added some tests

@RubenKelevra RubenKelevra marked this pull request as ready for review June 7, 2025 05:40
@RubenKelevra RubenKelevra marked this pull request as draft June 7, 2025 13:21
@RubenKelevra

Copy link
Copy Markdown
Contributor Author

I'll add the function which is described in the TODO/in your comment, I just can't complete it today anymore.

@westnordost westnordost reopened this Aug 13, 2025

@westnordost westnordost left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I guess it could be merged in the current state, too

@westnordost westnordost marked this pull request as ready for review August 13, 2025 19:36
@westnordost westnordost merged commit 917e155 into streetcomplete:master Aug 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants