Arhn - архитектура программирования

Groovy способ объединить два списка карт с некоторыми вычислениями

Мне нужно объединиться с картами, выполняя некоторые вычисления, например, имея следующие карты, которые всегда будут одинакового размера.

def map1 = [
    [name: 'Coord1', quota: 200],
    [name: 'Coord2', quota: 300]
]

def map2 = [
    [name: 'Coord1', copiesToDate: 270],
    [name: 'Coord2', copiesToDate: 30]
]

Я хочу получить эту карту

def map3 = [
    [name: 'Coord1', quota: 200, copiesToDate: 60, balance: 140],
    [name: 'Coord2', quota: 300, copiesToDate: 30, balance: 270]
]

Прямо сейчас я пытаюсь использовать это решение и его работу

def map4 = map1.collect { m1 ->
[
    name: m1.name,
    quota: m1.quota,
    copiesToDate: map2.find { m2 ->
        m1.name == m2.name
    }.copiesToDate,
    balanceToDate: m1.quota - map2.find { m2 ->
        m1.name == m2.name
    }.copiesToDate
]}

Не могли бы вы поделиться отличным способом выполнить эту задачу. Спасибо

13.02.2017

Ответы:


1

Самый крутой код, который я мог придумать:

def map3 = [map1, map2].transpose()*.sum().each { m ->
  m.balance = m.quota - m.copiesToDate
}

редактировать: как отметил Тим, этот код работает до тех пор, пока два входных списка (map1 и map2) имеют одинаковый размер и имеют карты в порядке. Если это не так, я бы порекомендовал ответ Тима, который обрабатывает эти случаи.

Вышеприведенное возвращает карту, как определено в вашем вопросе. Следующий код:

def list1 = [
    [name: 'Coord1', quota: 200],
    [name: 'Coord2', quota: 300]
]

def list2 = [
    [name: 'Coord1', copiesToDate: 60],
    [name: 'Coord2', copiesToDate: 30]
]

def x = [list1, list2].transpose()*.sum().each { m ->
  m.balance = m.quota - m.copiesToDate
}

x.each { 
  println it
}

демонстрирует идею и печатает:

[name:Coord1, quota:200, copiesToDate:60, balance:140]
[name:Coord2, quota:300, copiesToDate:30, balance:270]

Я переименовал map1 и map2 в list1 и list2, поскольку на самом деле это два списка, содержащие внутренние карты.

Код несколько лаконичен и может потребовать небольшого пояснения, если вы не привыкли к transpose и отличным операциям распространения и отображения.

Пояснение:

  1. [list1, list2] - сначала мы создаем новый список, где два существующих списка являются элементами. Итак, теперь у нас есть список списков, в котором элементы внутренних списков являются картами.
  2. .transpose() — затем мы вызываем transpose для понимания которого может потребоваться некоторое усилие, когда вы видите его в первый раз. Если у вас есть список списков, транспонирование можно рассматривать как переворачивание списков «в другом направлении».

В нашем случае два списка:

[[name:Coord1, quota:200], [name:Coord2, quota:300]]
[[name:Coord1, copiesToDate:60], [name:Coord2, copiesToDate:30]]

стали:

[[name:Coord1, quota:200], [name:Coord1, copiesToDate:60]]
[[name:Coord2, quota:300], [name:Coord2, copiesToDate:30]]

т. е. после транспонирования все, что относится к Coord1, находится в первом списке, а все, что относится к Coord2, — во втором.

  1. Каждый из списков, которые у нас есть сейчас, представляет собой список карт. Но нам нужна только одна карта для Coord1 и одна карта для Coord2. Итак, для каждого из приведенных выше списков нам теперь нужно объединить или объединить содержащиеся карты в одну карту. Мы делаем это, используя тот факт, что в groovy map+map возвращает объединенную карту. Таким образом, с помощью оператора Groovy Spread *. мы вызываем sum() для каждого списка. карт.

i.e.:

[[name:Coord1, quota:200], [name:Coord1, copiesToDate:60]].sum()

вычисляется в:

[name:Coord1, quota:200, copiesToDate:60]

и:

[[name:Coord2, quota:300], [name:Coord2, copiesToDate:30]].sum()

в:

[name:Coord2, quota:300, copiesToDate:30]
  1. наконец, мы хотим добавить свойство balance к картам, чтобы мы перебирали то, что теперь представляет собой список из двух карт, и добавляли баланс как вычисление квоты - copyToDate. Конструкция each возвращает список, над которым она работает, и это то, что мы присваиваем x.
13.02.2017
  • Транспонирование основано на списках, имеющих одинаковый порядок, без пропущенных элементов в каждом из них. 14.02.2017
  • Истинный. Поэтому для списков разной длины или порядка вам придется сделать что-то еще. В операторе прямо указано, что карты имеют одинаковый размер, который я решил прочитать как списки одинакового размера :). Для изменения порядка вы наиболее правы, транспонировать не получится. 14.02.2017

  • 2

    Еще один вариант развлечения :-)

    def result = (map1 + map2).groupBy { it.name }
                              .values()
                             *.sum()
                              .collect { it << ['balance': it.quota - it.copiesToDate] }
    
    • сложите списки вместе
    • группа по названию
    • получить сгруппированные значения и объединить их
    • затем для каждого из них разработайте balance
    13.02.2017

    3

    Не звоните find дважды. Используйте метод Map.plus() для добавления новых записей. Обработка отсутствующих имен из map2.

    def map3 = map1.collect {m1 ->
        def m2 = map2.find {it.name == m1.name} ?: [copiesToDate: 0]
        m1 + m2 + [balance: m1.quota - m2.copiesToDate]
    }
    
    13.02.2017
    Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..