list - 根据列的值使用 Groovy 重新组合列表
问题描述
我有一个包含街道地址、邮政编码、国家、省份等的列表......
我想连续重新组合同一条街道的所有门牌号码,例如:
City Street Cp Housenumber etc......
Qc Rue Prudent-Cloutier G0E 1V0 1-3,6,9-11
Qc Rue Godin G0E 1V0 102-104
.
.
.
.
所以我所做的是获取街道列的所有唯一值并将它们添加到一个新列表中,并将其与第一个列表与所有值进行比较,但我总是得到空值......
def str ='''\
<Table>
<Columns Items="6">
<Column Name="Id" Type="String"/>
<Column Name="Text" Type="String"/>
<Column Name="Highlight" Type="String"/>
<Column Name="Cursor" Type="Integer"/>
<Column Name="Description" Type="String"/>
<Column Name="Next" Type="String"/>
</Columns>
<Rows Items="8">
<Row Id="CA|CP|A|800140112" Text="1 Rue Prudent-Cloutier" Highlight="" Cursor="0" Description="Mont-Saint-Pierre, QC, G0E 1V0" Next="Retrieve"/>
<Row Id="CA|CP|A|15635710" Text="3 Rue Prudent-Cloutier" Highlight="" Cursor="0" Description="Mont-Saint-Pierre, QC, G0E 1V0" Next="Retrieve"/>
<Row Id="CA|CP|A|21493732" Text="6 Rue Prudent-Cloutier" Highlight="" Cursor="0" Description="Mont-Saint-Pierre, QC, G0E 1V0" Next="Retrieve"/>
<Row Id="CA|CP|A|16097589" Text="9 Rte Rue Prudent-Cloutier" Highlight="" Cursor="0" Description="Mont-Saint-Pierre, QC, G0E 1V0" Next="Retrieve"/>
<Row Id="CA|CP|A|17847787" Text="11 Rue Prudent-Cloutier" Highlight="" Cursor="0" Description="Mont-Saint-Pierre, QC, G0E 1V0" Next="Retrieve"/>
<Row Id="CA|CP|A|15997187" Text="102 Rue Municipale" Highlight="" Cursor="0" Description="Mont-Saint-Pierre, QC, G0E 1V0" Next="Retrieve"/>
<Row Id="CA|CP|A|15997137" Text="102 Rue Godin" Highlight="" Cursor="0" Description="Mont-Saint-Pierre, QC, G0E 1V0" Next="Retrieve"/>
<Row Id="CA|CP|A|15997149" Text="104 Rue Godin" Highlight="" Cursor="0" Description="Mont-Saint-Pierre, QC, G0E 1V0" Next="Retrieve"/>
</Rows>
</Table>
'''
def xml = new XmlParser().parseText(str)
List newAddressList=new ArrayList();
List StreetsAdress=new ArrayList();
List newUniqueList=new ArrayList();
def iter_String = xml.Rows[0].@Items
int iter = new Integer(iter_String).intValue()
z=0
for (int i=0; i < iter ; i++){
LastId = xml.Rows[0].Row[i].@Id
def (Country, Type) = LastId.tokenize( '\\|' )
Text = xml.Rows[0].Row[i].@Text
def (HouseNumber, Street) = Text.split(" " ,2)
if (HouseNumber!="CP"){
Description = xml.Rows[0].Row[i].@Description
def (City,City_ab,Code_postale ) = Description.tokenize( ',' )
newAddressList.add(['RecordId1':z++,'Country1 ':Country,'HouseNumber1':HouseNumber,'Street1': Street,'City1':City,'City_ab1':City_ab,'Code_postale1':Code_postale]);
StreetsAdress.add(['StreetList':Street]);
newUniqueList = StreetsAdress.unique();
}
}
println newUniqueList
所以我想知道如何比较 newUniqueList(仅包含没有重复的街道)和 newAddressList(包含所有信息)并重新组合所有 houseNumbers 。谢谢你的帮助 !
解决方案
以下代码:
import groovy.xml.*
def data = '''
<Table>
<Columns Items="6">
<Column Name="Id" Type="String"/>
<Column Name="Text" Type="String"/>
<Column Name="Highlight" Type="String"/>
<Column Name="Cursor" Type="Integer"/>
<Column Name="Description" Type="String"/>
<Column Name="Next" Type="String"/>
</Columns>
<Rows Items="8">
<Row Id="CA|CP|A|800140112" Text="1 Rue Prudent-Cloutier" Highlight="" Cursor="0" Description="Mont-Saint-Pierre, QC, G0E 1V0" Next="Retrieve"/>
<Row Id="CA|CP|A|15635710" Text="3 Rue Prudent-Cloutier" Highlight="" Cursor="0" Description="Mont-Saint-Pierre, QC, G0E 1V0" Next="Retrieve"/>
<Row Id="CA|CP|A|21493732" Text="6 Rue Prudent-Cloutier" Highlight="" Cursor="0" Description="Mont-Saint-Pierre, QC, G0E 1V0" Next="Retrieve"/>
<Row Id="CA|CP|A|16097589" Text="9 Rte Rue Prudent-Cloutier" Highlight="" Cursor="0" Description="Mont-Saint-Pierre, QC, G0E 1V0" Next="Retrieve"/>
<Row Id="CA|CP|A|17847787" Text="11 Rue Prudent-Cloutier" Highlight="" Cursor="0" Description="Mont-Saint-Pierre, QC, G0E 1V0" Next="Retrieve"/>
<Row Id="CA|CP|A|15997187" Text="102 Rue Municipale" Highlight="" Cursor="0" Description="Mont-Saint-Pierre, QC, G0E 1V0" Next="Retrieve"/>
<Row Id="CA|CP|A|15997137" Text="102 Rue Godin" Highlight="" Cursor="0" Description="Mont-Saint-Pierre, QC, G0E 1V0" Next="Retrieve"/>
<Row Id="CA|CP|A|15997149" Text="104 Rue Godin" Highlight="" Cursor="0" Description="Mont-Saint-Pierre, QC, G0E 1V0" Next="Retrieve"/>
</Rows>
</Table>
'''
def xml = new XmlSlurper().parseText(data)
def collapsed = xml.Rows.Row.groupBy { row ->
def matcher = row.@Text =~ /[^0-9]+/
matcher[0]
}.collect { street, rows ->
def nums = rows.collect { row ->
row.@Text.text().tokenize(' ').first() as Integer
}.sort()
def tokens = rows.first().@Description.text().tokenize(',')
def range = nums.size() == 1 ? "${nums.first()}" : "${nums.first()}-${nums.last()}"
[City: tokens[1].trim(), Street: street.trim(), Cp: tokens[2].trim(), HouseNumber: range]
}
def headers = ['City', 'Street', 'Cp', 'HouseNumber']
def widths = headers.collectEntries { header ->
[header, collapsed.collect { it[header].length() }.max() + 4]
}
headers.each { header ->
print(header.padRight(widths[header]))
}
println()
collapsed.each { row ->
headers.each { header ->
print(row[header].padRight(widths[header]))
}
println()
}
运行时,打印:
─➤ groovy solution.groovy
City Street Cp HouseNumber
QC Rue Prudent-Cloutier G0E 1V0 1-11
QC Rte Rue Prudent-Cloutier G0E 1V0 9
QC Rue Municipale G0E 1V0 102
QC Rue Godin G0E 1V0 102-104
...加倍努力,对输出进行了一些格式化,这使解决方案复杂化,但这应该为您提供一个如何使用它的示例。
由于这有点复杂,我将对代码的主要部分添加一些解释。
解释:
xml.Rows.Row.groupBy { row ->
def matcher = row.@Text =~ /[^0-9]+/
matcher[0]
}
这将获取由返回的行列表xml.Rows.Row
并将它们分组到 Row.Text 的非数字部分(即没有数字的街道名称,例如:“Rue Prudent-Cloutier”)。groupBy
返回 a Map<street name, List<Row>
,换句话说,按地址所在的街道分组的行(不包括数字)。
.collect { street, rows ->
...
}
这将遍历Map<street name, List<Row>>
并创建一个列表。换句话说,对于每条街道,这个闭包( 内部的部分{ }
)将使用街道名称(“Rue Prudent-Cloutier”)和rows
列表中具有该街道名称的所有行调用一次。将collect
返回一个List<something>
wheresomething
是这个闭包返回的任何内容。
def nums = rows.collect { row ->
row.@Text.text().tokenize(' ').first() as Integer
}.sort()
获取特定街道(例如“Rue Prudent-Cloutier”)的所有行,提取街道编号(1、3 等),将它们转换为整数并进行排序,以便nums
aList<Integer>
具有最小的数字,最大的最后。
def tokens = rows.first().@Description.text().tokenize(',')
拆分描述文本,例如Mont-Saint-Pierre, QC, G0E 1V0
返回 a 的逗号List<String>
(在本例中为 `['Mont-Saint-Pierre', 'QC', 'G0E 1V0'])。
def range = nums.size() == 1 ? "${nums.first()}" : "${nums.first()}-${nums.last()}"
获取已排序的门牌号码并创建单个数字字符串9
或范围字符串1-11
并将其存储在变量中range
。
[City: tokens[1].trim(), Street: street.trim(), Cp: tokens[2].trim(), HouseNumber: range]
这最终从.collect { street, rows -> ... }
. 这是 groovy map 语法,换句话说,collect 中的每次迭代都将返回一个 map,collapsed
因此将具有 type List<Map<String, String>>
,或者更简单的示例,collapsed
将具有以下结构:
[[City: QC, Street: Rue Prudent-Cloutier, Cp: G0E 1V0, HouseNumber:1-11],
[City: QC, Street: Rue Municipale, Cp: G0E 1V0, HouseNumber:102]
...
]
至于你应该把你的条件放在哪里,我认为你必须修改以适应你的需要。
推荐阅读
- sql-server - 使用 CASE 语句创建视图
- python - 创建项目后如何创建日期字段?
- razor-pages - razorpage 构造函数注入不起作用,而视图注入确实起作用
- react-native - 使用 AsyncStorage 的动态构建组件
- java - 如何在 SpannableString 的多个实例上显示不同的 toast 消息?
- javascript - 具有位置的旋转图像固定在 ReactJS 中动态更改旋转原点
- html - Vue.js 表单提交立即用 v-if 显示
- clickhouse - 未排序数组中的密集秩 (Clickhouse)
- javascript - 如何在javascript中修复“this.property is not iterable at window.onload”
- python-3.x - exec:名称未定义,但之前在同一代码中工作