arraysgroovygrails-2.5

Groovy/Grails - Modify dynamic array based on content


I have an array, which I get from a web service so it's always different but looks like this:

def originalArray = [
        [startDate:7 October 2017, endDate:14 October 2017, type:A],
        [startDate:7 October 2017, endDate:9 October 2017, type:A],
        [startDate:9 October 2017, endDate:14 October 2017, type:A],

        [startDate:7 October 2017, endDate:14 October 2017, type:B],

        [startDate:7 October 2017, endDate:9 October 2017, type:C],
        [startDate:9 October 2017, endDate:14 October 2017, type:C]]

Don't mind the date "formats" used, I'm writing it like that to simplify this question. What I'm trying to do is filter this array by type but also when there's occurrences where there's a fullweek, midweek and weekend that all occur across the same week and have the same type it should remove the midweek and weekend and give the fullweek a property called splittable set to true. So the above example will end up looking like this:

def moddedArray = [
    [startDate:7 October 2017, endDate:14 October 2017, type:A, splittable:true],

    [startDate:7 October 2017, endDate:14 October 2017, type:B, splittable:false],

    [startDate:7 October 2017, endDate:9 October 2017, type:C, splittable:false],
    [startDate:9 October 2017, endDate:14 October 2017, type:C, splittable:false]]

Here's what I've tried:

function startingFunction() {
    def weeks = getWeeks() // gets the array
    def fullWeeks = []
    weeks.each {
        def days = it.endDate - it.startDate
        if(days == 7) {
            fullWeeks.add(it)
        }
    }

    if(fullWeeks) {
        return applySplittable(fullWeeks,weeks)
    } else {
        return weeks
    }
}

function applySplittable(fullweeks,weeks) {
    def prelimWeeks = []
    def weeksSinglesRemoved = []

    fullweeks.eachWithIndex { f, i ->
        weeks.eachWithIndex { w, j ->
            if(!(f.type == w.type && (f.startDate == w.startDate || f.endDate == w.endDate) && (!(f.startDate == w.startDate && f.endDate == w.endDate)))) {
                prelimWeeks.add(w)
            }
        }
    }

    prelimWeeks.each { // when it gets here all the weeks will have been added as many times as there fullweeks, unless it's a midweek or weekend that have a fullweek
        if(Collections.frequency(prelimWeeks,it) >= fullweeks.size()) {
            weeksSinglesRemoved.add(it)
        }
    }

    return weeksSinglesRemoved.unique()
}

So as you can see, what I've tried is a mess and is probably not even that efficient but it works to remove the midweeks and weekends if there's a fullweek but it doesn't apply the splittable property. If anyone can provide me a way to get this done as simply as possible. Let me know if I need to supply more information.


Solution

  • I updated the applySplittable function, it now looks like this:

    def applySplittable(fullweeks, weeks) {
        def weeksSplit = []
        weeks.eachWithIndex { w, i ->
            def days = w.endDate - w.startDate
            if(days != 7) {
                def hasFull = fullweeks.findAll { w.type == it.type && (w.startDate == it.startDate || w.endDate == it.endDate) }
                if(!hasFull) {
                    w.splittable = false
                    weeksSplit.add(w)
                }
            } else {
                def hasSplit = weeks.findAll { w.type == it.type && (w.startDate == it.startDate || w.endDate == it.endDate) && !(w.startDate == it.startDate && w.endDate == it.endDate) }
                if(hasSplit) {
                    w.splittable = true
                } else {
                    w.splittable = false
                }
                weeksSplit.add(w)
            }
        }
        return weeksSplit
    }
    

    It's still a mess and it's probably still pretty inefficient but it seems to be working.