Convert a result set to another with a different structure?
I have 2 classes as shown:
public class Route {
public int node;
public int link;
public int weight;
}
The data in the node list will look like this:
node link weight
----------------------
1 A 0
1 B 10
2 C 5
2 D 8
2 E 12
Second class:
public class Segment{
public int node;
public String linkFrom, linkTo;
public int weight;
}
Is there an elegant solution to transform the above list into a new segment list that looks like this?
node linkfrom linkto weight
------------------------------------
1 A B 10
2 C E 25
The node list is converted to a segment list grouping
per node. The weight is the sum of the weights of these links in the node, a linkFrom
is the first link in the node, and linkTo
is the last link in the node before the group was changed.
source to share
Assuming for a specific node, for different links, each link will have different nodes. You can try adding a type function transform
and a custom comparator for your route class (or compareTo
and make it realistic ~ comparable to iterface) to compare routes by weight, I would go with a custom comparator because it doesn Look like comparison with weight is a natural comparison of routes ...
The code would be something like -
static class WeightComparator implements Comparator<Route>
{
public int compare(Route o1 , Route o2) {
if(o1.weight > o2.weight) {
return 1;
}
else if(o1.weight < o2.weight) {
return -1;
}
return 1;
}
public class Segment{
public int node;
public String linkFrom, linkTo;
public int weight;
public void transform(int node, List<Route> routes) {
List<Route> routesWithNode = new ArrayList<Route>();
for(Route route : routes) {
if(route.node == node) {
routesWithNode.add(route);
}
}
Collections.sort(routesWithNode , new WeightComparator());
this.node = node;
this.linkFrom = routesWithNode.get(0).link;
this.linkTo = routeWithNode.get(routesWithNode.length - 1).link;
int tweight = 0;
for(Route r: routeWithNode) {
tweight = tweight + r.weight;
}
this.weight = tweight;
}
}
Then in your main or wherever you need to create these segments, for each unique node in the route list, you can do -
for uniqueNode in routeList:
segmentList.add(new Segment().transform(uniqueuNode, routeList)
Please note that above is not java code, its pseudo code, you need to write complete code.
source to share
Add a new class called Convert
public class Convert{
public Route firstRoute;
public Route lastRoute;
public Segment segment;
public Convert(){
this.segment = new Segment();
}
}
Then create a map of all routes to identify the first member in the list of all routes.
public HashMap<Integer,Route> map = new HashMap<>();
Create Convert list to store converted list data
public List<Convert> convertedList = new ArrayList<>();
Then iterations
for(int i=0;i<routes.size();i++){
Route route = routes.get(i);
Convert convert = new Convert();
if(map.get(route.node)!=null){
convert.lastRoute = route;
convert.segment.linkTo=String.valueOf(route.link);
}else{
map.put(route.node);
convert.firstRoute = route;
convert.segment.node=route.node;
convert.segment.linkFrom=String.valueOf(route.link);
}
convert.segment.weight+=route.weight;
convertedList.add(convert);
}
for(Convert con:convertedList)[
//Print in the required format
}
I made the assumption that you want the last link in the route list to always be as linkTo in the segment.
source to share
I created below code. It's pretty rude.
public void convert() {
// List to hole segments
ArrayList<Segment> segments = new ArrayList<Segment>();
// List holding routes
ArrayList<Route> routes = createRoutes();
// Node id
int startRouteNode = routes.get(0).node;
// Start Link
String startLink = null;
// Link in previous node traversed
String previousLink = null;
// Weight
int weight = 0;
for (Route route : routes) {
// If current route is on the same node as previous one
if (startRouteNode == route.node) {
if (startLink == null)
startLink = route.link;
previousLink = route.link;
weight += route.weight;
} else {
// If current route is not on previous node
segments.add(new Segment(startRouteNode, startLink,
previousLink, weight));
startRouteNode = route.node;
startLink = previousLink;
weight = route.weight;
}
}
// Add last segment in segment list
segments.add(new Segment(startRouteNode, startLink, previousLink,
weight));
System.out.println(segments);
}
ArrayList<Route> createRoutes() {
ArrayList<Route> arraylist = new ArrayList<Route>();
arraylist.add(new Route(1, "A", 0));
arraylist.add(new Route(1, "B", 10));
arraylist.add(new Route(2, "C", 5));
arraylist.add(new Route(2, "D", 8));
arraylist.add(new Route(2, "E", 12));
return arraylist;
}
source to share