Home > Software design >  Is there a way to find an element in a list and delete items after it that are of a specific type wi
Is there a way to find an element in a list and delete items after it that are of a specific type wi

Time:08-05

I have a project that needs me to remove items if one of the properties of the item I'm trying to find within the list is true. Just so it's easier understand the project I am pasting all code needed to understand it below.

fun main() {
    val acct1 = AccountId(72)

    val calendars = mutableListOf<CalendarDrawerCalendarItem>()
    val calendars2 = mutableListOf<CalendarDrawerCalendarItem>()

    calendars.add(CalendarDrawerCalendarItem(CalendarDescriptor(acct1, CalendarId(acct1, 3),"toast", true)))
    calendars.add(CalendarDrawerCalendarItem(CalendarDescriptor(acct1, CalendarId(acct1, 4), "chicken", false)))
    calendars.add(CalendarDrawerCalendarItem(CalendarDescriptor(acct1, CalendarId(acct1, 5), "pizza", true)))
    calendars2.add(CalendarDrawerCalendarItem(CalendarDescriptor(acct1, CalendarId(acct1, 1), "bagel", true)))

// These are example calls to collapse

    collapse(calendars, CalendarDrawerGroupItem(true, CalendarGroupDescriptor( acct1, "My Calendars")))
    collapse(calendars2, CalendarDrawerGroupItem(false, CalendarGroupDescriptor(acct1, "Group Calendars")))
}

fun collapse(calendars: List<CalendarDrawerListItem>, group: CalendarDrawerGroupItem): List<CalendarDrawerListItem> {

    val collapsedResults = mutableListOf<CalendarDrawerListItem>()
    val findGroupGiven = group

    collapsedResults.addAll(calendars)
    
    if (collapsedResults.contains(findGroupGiven)) {
        group.collapsed = true
        // logic for deleting items here

    }

    return collapsedResults
}

I'll also put the classes so you can see how they're defined

data class AccountId(
    val accountId: Int
)

data class CalendarId(
    val accountId: AccountId,
    val calendarId: Int)

data class CalendarDescriptor(
    val accountId: AccountId,
    val calendarId: CalendarId,
    val name: String,
    val isGroupCalendar: Boolean
)

data class CalendarGroupDescriptor(
    val accountId: AccountId,
    val name: String,
)


sealed class CalendarDrawerListItem

data class CalendarDrawerGroupItem(var collapsed: Boolean, val groupDescriptor: CalendarGroupDescriptor) : CalendarDrawerListItem()

data class CalendarDrawerCalendarItem(val calendarDescriptor: CalendarDescriptor) : CalendarDrawerListItem()

The first step I have done is I must find the given group from the group variable, within calendars. (I did this with the contains() method). Next when I find the group I have to set its collapsed variable to true and any CalendarDrawerCalendarItems after it have to be deleted.

The input will look something like (the exact numbers and values are not the important part):

Input: 
calendars:
CDGroupItem(collapsed = false, groupDescriptor = GroupDescriptor(accountId = 1, name = "My calendars"))
CDCalendarItem(calendarDescriptor = CalendarDescriptor(accountId = 1, calendarId = 1, isGroup = false))
CDCalendarItem(calendarDescriptor = CalendarDescriptor(accountId = 1, calendarId = 2, isGroup = false))
CDCalendarItem(calendarDescriptor = CalendarDescriptor(accountId = 1, calendarId = 3, isGroup = false))
CDGroupItem(collapsed = false, groupDescriptor = GroupDescriptor(accountId = 1, name = "Group calendars"))
CDCalendarItem(calendarDescriptor = CalendarDescriptor(accountId = 1, calendarId = 4, isGroup = true))
CDCalendarItem(calendarDescriptor = CalendarDescriptor(accountId = 1, calendarId = 5, isGroup = true))



group: CDGroupItem(collapsed = false, groupDescriptor = GroupDescriptor(accountId = 1, name = "My calendars"))

The output should look something like this:

Output:
CDGroupItem(collapsed = true, groupDescriptor = GroupDescriptor(accountId = 1, name = "My calendars"))
CDGroupItem(collapsed = false, groupDescriptor = GroupDescriptor(accountId = 1, name = "Group calendars"))
CDCalendarItem(calendarDescriptor = CalendarDescriptor(accountId = 1, calendarId = 4, isGroup = true))
CDCalendarItem(calendarDescriptor = CalendarDescriptor(accountId = 1, calendarId = 5, isGroup = true))

Any group item that has its collapsed boolean set to true should have all calendar items deleted after it since its collapsed is set to true. Again the names and numbers are not super important. The collapsed bool is. How can I do this without hardcoding or using indicies?

CodePudding user response:

Your example code doesn't use that input and output as-is so I can only give you a general example, but you could use a fold:

val result = calendars.fold(mutableListOf<CalendarDrawerListItem>()) { items, current ->
    // basically 'is there a last item stored, and is it a group item, and is it collapsed'
    val lastStoredIsCollapsed =
        (items.lastOrNull() as? CalendarDrawerGroupItem)?.collapsed == true
    if (current is CalendarDrawerCalendarItem && lastStoredIsCollapsed) items
    else items.apply { add(current) }
}

It basically pipes out each item into a list, but if the last one it stored is a CalendarDrawerGroupItem with collapsed set to true, it drops drawer items. If the last one is a non-collapsed group item, it can store a drawer item, and that means the next drawer item will be stored (since the last item isn't a collapsed group)


edit: here's the for loop equivalent if it helps, with the full logic for when a calendar is not dropped (the logic in my other example is for whether it should be dropped, which can be condensed a bit):

// assuming 'calendars' is your list of items with 'collapsed' set appropriately
val result = mutableListOf<CalendarDrawerListItem)
for (calendar in calendars) {
    val lastStored = result.lastOrNull()
    when {
        lastStored == null ->
            result.add(calendar)
        lastStored is CalendarDrawerGroupItem && !lastStored.collapsed ->
            result.add(calendar)
        lastStored is CalendarDrawerCalendarItem ->
            result.add(calendar)
    }
}
return result

If you're asking how to actually mutate your list so a collapsed property is set to true, that would be easy if the property was a var in your data class. Since it's a val you'll have to do something like this:

val calendarInputWithCollapsedSet = calendars.map { calendar ->
    if ((calendar as? CalendarDrawerGroupItem)?.groupDescriptor == group.groupDescriptor)
        calendar.copy(collapsed = true) else calendar
}

So if you find a matching group (you'll have to work out how to match them, I'm guessing) you transform it into a copy with its collapsed property set

And then you can run the fold or whatever on that new list.

  • Related