sort two lists by their first element and zip them in scala

半世苍凉 提交于 2019-12-12 23:39:49

问题


 val descrList = cursorReal.interfaceInfo.interfaces.map {
    case values => (values.ifIndex , values.ifName , values.ifType)
  }

 val ipAddressList = cursorReal.interfaceIpAndIndex.filter(x=> (!x.ifIpAddress.equalsIgnoreCase("0"))).map {
    case values => (values.ifIndex,values.ifIpAddress)
  }

For instance,

val descrList = 
  List((12,"VoIP-Null0",1), (8,"FastEthernet6",6), (19,"Vlan11",53),
       (4,"FastEthernet2",6), (15,"Vlan1",53), (11,"GigabitEthernet0",6),
       (9,"FastEthernet7",6), (22,"Vlan20",53), (13,"Wlan-GigabitEthernet0",6), 
       (16,"Async1",1), (5,"FastEthernet3",6), (10,"FastEthernet8",6), 
       (21,"Vlan12",53), (6,"FastEthernet4",6), (1,"wlan-ap0",24), 
       (17,"Virtual-Template1",131), (14,"Null0",1), (20,"Vlan10",53), 
       (2,"FastEthernet0",6), (18,"NVI0",1), (7,"FastEthernet5",6), 
       (29,"Virtual-Access7",131), (3,"FastEthernet1",6), (28,"Virtual-Access6",131))

val ipAddressList = List((21,"192.168.12.1"), (19,"192.168.11.1"), 
                         (11,"104.36.252.115"), (20,"192.168.10.1"), 
                         (22,"192.168.20.1"))

In both the lists first element is index and i have to merge these two list index wise . It means (21,"192.168.12.1") this ipAddress should merge with (21,"Vlan12",53) and form new list like below (21,"Vlan12",53,"192.168.12.1").


回答1:


scala> descrList map {case (index, v1, v2) =>
   (index, v1, v2, ipAddressList.toMap.getOrElse(index, "empty"))}
res0: List[(Int, String, Int, String)] = List(
(12,VoIP-Null0,1,empty), (8,FastEthernet6,6,empty), (19,Vlan11,53,192.168.11.1), 
(4,FastEthernet2,6,empty), (15,Vlan1,53,empty), (11,GigabitEthernet0,6,104.36.252.115), 
(9,FastEthernet7,6,empty), (22,Vlan20,53,192.168.20.1), (13,Wlan-GigabitEthernet0,6,empty), 
(16,Async1,1,empty), (5,FastEthernet3,6,empty), (10,FastEthernet8,6,empty), 
(21,Vlan12,53,192.168.12.1), (6,FastEthernet4,6,empty), (1,wlan-ap0,24,empty), (17,Virtual-
Template1,131,empty), (14,Null0,1,empty), (20,Vlan10,53,192.168.10.1), (2,FastEthernet0,6,empty),
(18,NVI0,1,empty), (7,FastEthernet5,6,empty), (29,Virtual-Access7,131,empty),
(3,FastEthernet1,6,empty), (28,Virtual-Access6,131,empty))



回答2:


First, I would suggest you produce a Map instead of a List. A Map by nature has an indexer, and in your case this would be the ifIndex value.

Once you have Maps in place, you can use something like this (sample from this other SO Best way to merge two maps and sum the values of same key?)

From Rex Kerr: map1 ++ map2.map{ case (k,v) => k -> (v + map1.getOrElse(k,0)) }

Or like this from Matthew Farwell: (map1.keySet ++ map2.keySet).map (i=> (i,map1.getOrElse(i,0) + map2.getOrElse(i,0))}.toMap

If you cannot use Maps for whatever reason, then look into your existing project libraries. If you have Scalaz, then you have some tools already available.

Scalaz: https://github.com/scalaz/scalaz

If you have Slick, you also have some nice tools to directly use.

Slick: http://slick.typesafe.com/docs/




回答3:


Consider first converting decrList to a Map, like this,

val a = (for ( (k,v1,v2) <- descrList) yield k -> (v1,v2)).toMap

Then we can look up keys for ipAddressList and agglomerate elements into a new tuple, as follows,

for ( (k,ip) <- ipAddressList ; v = a.getOrElse(k,("none","none")) ) yield (k,v._1,v._2,ip)

Hence, for ipAddressList,

res: List((21,Vlan12,53,192.168.12.1), (19,Vlan11,53,192.168.11.1), 
          (11,GigabitEthernet0,6,104.36.252.115), (20,Vlan10,53,192.168.10.1),
          (22,Vlan20,53,192.168.20.1))



回答4:


Given the data:

val descrList =
  List((12, "VoIP-Null0", 1), (8, "FastEthernet6", 6), (19, "Vlan11", 53),
    (4, "FastEthernet2", 6), (15, "Vlan1", 53), (11, "GigabitEthernet0", 6),
    (9, "FastEthernet7", 6), (22, "Vlan20", 53), (13, "Wlan-GigabitEthernet0", 6),
    (16, "Async1", 1), (5, "FastEthernet3", 6), (10, "FastEthernet8", 6),
    (21, "Vlan12", 53), (6, "FastEthernet4", 6), (1, "wlan-ap0", 24),
    (17, "Virtual-Template1", 131), (14, "Null0", 1), (20, "Vlan10", 53),
    (2, "FastEthernet0", 6), (18, "NVI0", 1), (7, "FastEthernet5", 6),
    (29, "Virtual-Access7", 131), (3, "FastEthernet1", 6), (28, "Virtual-Access6", 131))

val ipAddressList = List((21, "192.168.12.1"), (19, "192.168.11.1"),
  (11, "104.36.252.115"), (20, "192.168.10.1"),
  (22, "192.168.20.1"))

Merge and sort:

val addrMap = ipAddressList.toMap

val output = descrList
  .filter(x => addrMap.contains(x._1))
  .map(x => x match { case (i, a, b) => (i, a, b, addrMap(i)) })
  .sortBy(_._1)

output foreach println

Output:

(11,GigabitEthernet0,6,104.36.252.115)
(19,Vlan11,53,192.168.11.1)
(20,Vlan10,53,192.168.10.1)
(21,Vlan12,53,192.168.12.1)
(22,Vlan20,53,192.168.20.1)


来源:https://stackoverflow.com/questions/26323916/sort-two-lists-by-their-first-element-and-zip-them-in-scala

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!