使用Groovy或Java比较两个映射并找出差异 [英] Compare two maps and find differences using Groovy or Java

查看:135
本文介绍了使用Groovy或Java比较两个映射并找出差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在两张地图上找到差异,并创建一个新的csv文件,其中包含以下差异(并将差异放在**之间):

地图1

  [
[cuInfo:T12,service:3,startDate:14-01-16 1322,appId:G12355],
[cuInfo:T13,service:3,startDate:12-02-16 13:00,appId:G12356],
[cuInfo:T14,服务:9,startDate:10-01-16 11:20,appId:G12300],
[cuInfo:T15,service: 10,startDate:26-02-16 10:20,appId:G12999]
]

地图2

  [
[name:Apple,cuInfo:T12, service:3,startDate:14-02-16 10:00,appId:G12351],
[name:Apple,cuInfo:T13,service:3,startDate :14-01-16 13:00,appId:G12352],
[名称:Apple,cuInfo:T16,服务:3,startDate:14-01-16 13:00,appId:G12353],
[name:Google,cuInfo:T14,service:9,startDate:10-01-16 11:20,appId: G12301],
[名称:Microsoft,cuInfo:T15 ,service:10,startDate:26-02-16 10:20,appId:G12999],
[name:Microsoft,cuInfo:T18,service:10 ,startDate:26-02-16 10:20,appId:G12999]
]

我怎样才能得到如下所示的输出csv?

  Map 1 data |地图2数据
服务3;名称Apple;
cuInfo; startDate; appId | cuInfo; startDate; appId
T12; * 14-02-16 10:00 *; * G12351 * | T12; * 14-01-16 13:22 *; * G12355 *
T13; * 14-01-16 13:00 *; * G12352 * | T13; * 12-02-16 13:00 *; * G12356 *
服务9;名称为Google;
T14; * 10-01-16 11:20 *; * G12301 * | T12; * 10-01-16 11:20 *; * G12300 *

谢谢

解决方案

在下面的例子中,我假设地图列表被适当地排序,以便比较公平,并且这两个列表都是相同的长度:

首先,创建一个 Iterator 来同时遍历两个列表:

  @ groovy.transform.TupleConstructor 
class DualIterator实现Iterator< List> {
Iterator iter1
Iterator iter2

布尔hasNext(){
iter1.hasNext()&& iter2.hasNext()
}

列表next(){
[iter1.next(),iter2.next()]
}

void remove(){
throw new UnsupportedOperationException()
}
}

接下来,处理列表以获取CSV文件的行:

  def rows = new DualIterator(list1 .iterator(),list2.iterator())
.findAll {it [0]!= it [1]} //获取不匹配的行。
.collect {//标记不匹配的值。
(m1,m2)= it
m1.keySet()。each {key - >
if(m1 [key]!= m2 [key]){
m1 [key] =* $ {m1 [key]} *
m2 [key] =* $ {m2 [key]} *
}
}

[m1,m2]
} .collect {//将地图值合并到字符串列表中数组
[it [0] .values(),it [1] .values()]。flatten()as String []
}
pre>

最后,以CSV格式写出标题和行。注意:我使用的是正确的CSV;您的示例实际上是无效,因为列数不一致:

  def writer = new CSVWriter新的FileWriter('blah.csv'))
writer.writeNext(['name1','cuInfo1','service1','startDate1','appId1','name2','cuInfo2','service2' ,'startDate2','appId2'] as String [])
writer.writeAll(rows)
writer.close()

输出如下所示:

 name1,cuInfo1, service1,startDate1,appId1,name2,cuInfo2,service2,startDate2,appId2
Apple,T12,3,* 14 -02-16 10:00 *,* G12351 *,Apple,T12,3,* 14-01-16 13:22 *,* G12355 *
Apple,T13,3,* 14-01-16 13:00 *,* G12352 *,Apple,T13,3,* 12-02-16 13:00 *,* G12356 *,
Google,T14,9,10-01-16 11:20,* G12301 *,Google,T14 ,9,10-01-16 11:20,* G12300 *


I would like to find difference in two maps and create a new csv file with the difference (and put the difference between **) like below:

Map 1

  [
    [cuInfo:"T12",service:"3",startDate:"14-01-16 13:22",appId:"G12355"],
    [cuInfo:"T13",service:"3",startDate:"12-02-16 13:00",appId:"G12356"],
    [cuInfo:"T14",service:"9",startDate:"10-01-16 11:20",appId:"G12300"], 
    [cuInfo:"T15",service:"10",startDate:"26-02-16 10:20",appId:"G12999"]  
]

Map 2

[
    [name:"Apple", cuInfo:"T12",service:"3",startDate:"14-02-16 10:00",appId:"G12351"],
    [name:"Apple",cuInfo:"T13",service:"3",startDate:"14-01-16 13:00",appId:"G12352"],
    [name:"Apple",cuInfo:"T16",service:"3",startDate:"14-01-16 13:00",appId:"G12353"],
    [name:"Google",cuInfo:"T14",service:"9",startDate:"10-01-16 11:20",appId:"G12301"], 
    [name:"Microsoft",cuInfo:"T15",service:"10",startDate:"26-02-16 10:20",appId:"G12999"],
    [name:"Microsoft",cuInfo:"T18",service:"10",startDate:"26-02-16 10:20",appId:"G12999"]  
]   

How can I get the output csv like below

Map 1 data | Map 2 data
service 3;name Apple;
cuInfo;startDate;appId | cuInfo;startDate;appId
T12;*14-02-16 10:00*;*G12351* | T12;*14-01-16 13:22*;*G12355*
T13;*14-01-16 13:00*;*G12352* | T13;*12-02-16 13:00*;*G12356*
service 9;name Google;       
T14;*10-01-16 11:20*;*G12301* | T12;*10-01-16 11:20*;*G12300*   

Thanks

解决方案

In the following I'm assuming that the list of maps is sorted appropriately so that the comparison is fair, and that both lists are of the same length:

First, create an Iterator to traverse both lists simultaneously:

@groovy.transform.TupleConstructor
class DualIterator implements Iterator<List> {
    Iterator iter1
    Iterator iter2

    boolean hasNext() {
        iter1.hasNext() && iter2.hasNext()
    }

    List next() {
        [iter1.next(), iter2.next()]
    }

    void remove() {
        throw new UnsupportedOperationException()
    }
}

Next, process the lists to get rows for the CSV file:

def rows = new DualIterator(list1.iterator(), list2.iterator())
    .findAll { it[0] != it[1] } // Grab the non-matching lines.
    .collect { // Mark the non-matching values.
        (m1, m2) = it
        m1.keySet().each { key ->
            if(m1[key] != m2[key]) {
                m1[key] = "*${m1[key]}*"
                m2[key] = "*${m2[key]}*"
            }          
        }

        [m1, m2]
    }.collect { // Merge the map values into a List of String arrays
        [it[0].values(), it[1].values()].flatten() as String[]
    }

Finally, write the header and rows out in CSV format. NOTE: I'm using a proper CSV; your example is actually invalid because the number of columns are inconsistent:

def writer = new CSVWriter(new FileWriter('blah.csv'))
writer.writeNext(['name1', 'cuInfo1', 'service1', 'startDate1', 'appId1', 'name2', 'cuInfo2', 'service2', 'startDate2', 'appId2'] as String[])
writer.writeAll(rows)
writer.close()

The output looks like this:

"name1","cuInfo1","service1","startDate1","appId1","name2","cuInfo2","service2","startDate2","appId2"
"Apple","T12","3","*14-02-16 10:00*","*G12351*","Apple","T12","3","*14-01-16 13:22*","*G12355*"
"Apple","T13","3","*14-01-16 13:00*","*G12352*","Apple","T13","3","*12-02-16 13:00*","*G12356*"
"Google","T14","9","10-01-16 11:20","*G12301*","Google","T14","9","10-01-16 11:20","*G12300*"

这篇关于使用Groovy或Java比较两个映射并找出差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆