Is there something similar to `Collections.groupBy...
# announcements
t
Is there something similar to
Collections.groupBy
that allows you to specify a grouping function? I have a list of Songs. I’d like to group them together, using the following logic (psuedo-code)
Copy code
val group = if (album name matches) {
    if (artist name matches) { 
        true 
    } else {
        if (album-artist name matches) {
            true
        }
    }
    false
}
Hmm, I suspect this doesn’t make sense.. grouping requires a key, and I’m not sure a key can be derived from the above logic
n
not sure what you try to accomplish. Your pseudo-code returns a boolean. Are you expecting 2 collections as a result based on that boolean?
then
partition
would help
e
I think you have an inconsistent grouping there. [(artist=a, album-artist=A), (artist=b, album-artist=B)] = 2 groups add [(artist=a, album-artist=B)] = how many groups?
t
Sorry, the boolean is meant to represent whether two songs should be grouped together
e
in other words, your grouping isn't transitive
t
I’m having trouble expressing myself, I’ve been thinking about this for too long, now my brain is malfunctioning
I’m trying to collect songs that belong together on an album. Two songs belong together on an album, if the album name (String) matches, and a) the artists (List<String>) of the song matches, or b) the album-artist name (String) matches
Is that ‘non-transitive’ grouping? Is that problematic?
e
what if songs a, b, c have the same album name, a.artists = b.artists, b.album-artist = c.album-artist, but a does not have any properties in common with c
according to your rules, a and b are in the same group, b and c are in the same group, but a and c are not in the same group
t
Right, so this is exactly the problem I’m having trouble expressing
In this case, I think I’d like the group of b and c to ‘adopt’ a, and modify a’s album-artist property
e
this is easily extendable to two groups with different album-artists, with a subset with a common artist
you don't have any way of resolving this
t
OK. I understand. I have an outcome in mind that is achievable (can be resolved), but obviously not by the condition that I’ve provided here
I think what I want to do is.. If the album-artist of a song is null, then the artist name is used. Then songs are grouped by album name and this derived album-artist/artist name
e
- song A : artist=foo album-artist=foo - song B : artist=bar album-artist=foo - song C : artist=bar album-artist=bar - song D : artist=foo album-artist=bar
do you group them all together, and if so, what is the album-artist?
(assuming all have the same album name)
t
No. A and B would be grouped, and C and D would be grouped. (Since album-artist is present)
e
but A and D would be grouped under your rules?
unless you are saying "ignore artist if album-artist is present", which is a different (and consistent) ruleset
t
Yes, that’s what I’m saying.
If the album-artist of a song is null, then the artist name is used
Which to me is “ignore artist if album-artist is present”"
e
that's the inversion, which doesn't logically follow, but sure
t
Do you mind explaining why that statement doesn’t logically follow?
e
P→Q does not imply ¬P→¬Q
1
t
Sorry, I’m not familiar with this notation
e
"if album-artist is null then use artist name" does not imply "if album-artist is not null then don't use artist name" - in fact it says nothing about that case
👍 1
t
I think you’ve helped me get a grasp on what I’m trying to do tho haha
Oh, OK - I understand what you’re saying
P→Q does not imply ¬P→¬Q
What is this notation, by the way?
e
standard boolean algebra
t
Thanks. I haven’t come across this before.
Alright. So I’d like to group songs together, if their album name matches and a) by their album-artist name if it exists b) by their artist name if album-artist name does not exist I think there are probably a few different ways to achieve this. Any idea if there’s a concise, kotlin collections way to do this? I’m thinking maybe I’d create a class:
data class GroupKey(val album: String, val albumArtistOrArtist: String)
And then
songs.groupBy { GroupKey(it.album, it.albumArtist ?: it.artist) }
I guess I could just use a Pair instead
m
don’t use a Pair, try to create a meaningful type for your domain; a generic tuple is always harder to read and bears almost no semantic except “some data together”
t
OK, yeah, fair enough. I did go with a class instead.
🆒 1
s
hopefully a data class.
m
Why should it be a data class? Do you have some guidelines or heuristics you use to decide?
t
I would assume it's being recommended for the convenience of automatically generated equals/hashCode functions. These functions are required for
groupBy()
to work, and must correctly distinguish two instances of this class by its parameters