Создание карт данных узла ответа XML в Groovy - PullRequest
0 голосов
/ 10 мая 2018

Я пытаюсь сохранить значения узлов ответа XML на карте, но это ДЕЙСТВИТЕЛЬНО сложно. Вот XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<SearchRS>
    <SearchStatus>SUCCESS</SearchStatus>
    <Itinerary>
        <Name>Joe</Name>
        <Ticket>111.11</Ticket>
        <Taxes>1.11</Taxes>
    </Itinerary>
    <Itinerary>
        <Name>Bob</Name>
        <Ticket>222.22</Ticket>
        <Taxes>2.22</Taxes>
    </Itinerary>
    <Itinerary>
        <Name>Joe</Name>
        <Ticket>333.33</Ticket>
        <Taxes>3.33</Taxes>
        </Itinerary>
    <Itinerary>
    <Itinerary>
        <Name>Bob</Name>
        <Ticket>444.44</Ticket>
        <Taxes>4.44</Taxes>
    </Itinerary>
        <Name>Joe</Name>
        <Ticket>0.0</Ticket>
        <Taxes>0.0</Taxes>
    </Itinerary>
</SearchRS>

Мне нужно рассчитать средний билет + налоги для каждого имени.

Примечание. Любое значение 0,0 должно быть исключено из среднего значения.

Я хочу создать карту, которая будет содержать следующее:

[ name : average of ticket+taxes value] 

То, что я пробовал, это найдет минимальное значение для каждого, документ. Маршрут содержит ответ XML.

  def minByName = doc.Itinerary
            .inject([:].withDefault { [] }) { map, it ->
       map[it.Name.text()] << it
       map
  }
  .collectEntries { profile, nodes ->
       [profile, nodes.min { it.Ticket.text() as Double }]
  }

  def nameList = []
    minByName.each { profile, minimum ->
        Map nameMap = [:]
        nameMap.name = profile
        nameMap.ticket = minimum.Ticket.toString()
        nameMap.taxes = minimum?.Taxes
        nameList << nameMap
  }
 log.info("Cheapest ticket and tax per name: " + nameList)

Что приведет к набору данных для каждого имени:

[[name:Joe, ticket:111.11, taxes:1.11], [name:Bob, etc...]]

Вместо минимума я хочу, чтобы значения на карте были средними, например, для всех билетов Джо + налоги.

Что бы выглядело так:

[[name:Joe, averageCost:224.44], [name:Bob, averageCost...]]

111,11 + 1,11 = 112,22, 333,33 + 3,33 = 336,66. 112,22 + 336,66 = 448,88. 448,88 / 2 = 224,44

Я действительно застрял на этом, любая помощь очень ценится!

Ответы [ 2 ]

0 голосов
/ 10 мая 2018

Если я правильно понял,

def root = new XmlSlurper().parse(new File ('/tmp/stack.xml'))

List <String> names = root.'**'.findAll{ it.name() == "Name"}.collect{it}

List <Map> totalresult = []

names.unique().each{name ->

    Map result = [:]

    result["name"] = name

    List<Float> tickets = root.'**'.findAll{ it.Name == name && it.Ticket.toFloat() > 0.0}.collect { it.Ticket.toFloat() + it.Taxes.toFloat() }

    result ["total"] = tickets.sum()

    result ["occurances"]= tickets.size()

    result ["avgCosts"] = result.total/result.occurances

    totalresult.add(result)

}

println totalresult

Обновление 1: код исправлен согласно требованию.

0 голосов
/ 10 мая 2018

Посмотрите, что вы ищете (объясненный комментарий в строке):

//pass xmlString to below
def xml = new XmlSlurper().parseText(xmlString)
def map = [:]
//Find unique names, then  respective Iteneraries, then collect ticket & taxes, convert to Double, eliminate 0 values, sum and average, put into map
xml.'**'.findAll {it.name() == 'Name'}.unique().each { name -> 
   map[name] = xml.'**'.findAll {it.name() == 'Itinerary' && name == it.Name.text() }.collect { Double.parseDouble(it.Ticket.text()) + Double.parseDouble(it.Taxes.text())}.findAll {it}.with { sum() / size() }
}
println map

Пожалуйста, найдите быстрое демо

РЕДАКТИРОВАТЬ: Обращаясь к комментарию ОП.

Изменить sum() на sum().round(2)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...