sampleData = [{
RouteId: "1",
InDirection: "1",
AreaCode: ["41108", "41109", "41110", "41111"],
}, {
RouteId: "1",
InDirection: "2",
AreaCode: ["41108", "41109", "411011"],
}, {
RouteId: "2",
InDirection: "1",
AreaCode: ["41112", "41114"],
}, {
RouteId: "2",
InDirection: "2",
AreaCode: ["41112", "41114"],
}, {
RouteId: "3",
InDirection: "1",
AreaCode: ["41112", "41114"],
}, {
RouteId: "3",
InDirection: "2",
AreaCode: ["41112", "41114","41108", "41109", "41110"],
}, {
RouteId: "4",
InDirection: "1",
AreaCode: ["41112", "41114","41108", "41110" , "41120", "41121"],
}, {
RouteId: "4",
InDirection: "2",
AreaCode: ["41112", "41114"],
}]
I want to sort above sampleData
based on number of entries in AreaCodes
and get top 20
results. But I only want one object every RouteId
. Every RouteId
can have two types of InDirection = 1 or 2
. So in the above result would like to removed
{
RouteId: "1",
InDirection: "2",
AreaCode: ["41108", "41109", "411011"],
}
since it less entires on AreaCode
as compared to InDirection= 1
so the final sorted result should be
finalResult = [{
RouteId: "1",
InDirection: "1",
AreaCode: ["41108", "41109", "41110", "41111"],
}, {
RouteId: "2",
InDirection: "1",
AreaCode: ["41112", "41114"],
}, {
RouteId: "3",
InDirection: "2",
AreaCode: ["41112", "41114","41108", "41109", "41110"],
}, {
RouteId: "4",
InDirection: "1",
AreaCode: ["41112", "41114","41108", "41110" , "41120", "41121"],
}]
Here I got so far:
const filteredItems = sampleData.filter(item => {
const otherItem = transformedData.find(i => i.RouteId === item.RouteId && i.InDirection !== item.InDirection);
if (otherItem) {
return item.AreaCode.length > otherItem.AreaCode.length;
} else {
return true;
}
});
But this missed condition where length of AreaCode
is equal and the final result is not sorted.
3
Answers
You want to make use of
sort
andfilter
functions for arrays, though there may be other ways of doing thins.You may also want to use something like Lodash, (if you’re not opposed to using an external library), perhaps uniquBy might be something of interest (or sortedUinqBy ?)
You can do this in steps
Array#sort
in descending order of mostAreaCode
sArray#reduce
to exclude any element whoseRouteId
already exists prior to the elements indexI personally don’t think
filter()
is the best solution here.If you know that the provided structure always provides exactly two items with the same
RouteId
after each other. Then you can chunk the array in chunks of size 2. Thenmap()
each chunk by comparing the two elements based onAreaCode.length
.The code above uses a
chunkN()
helper that I’ve defined in the snippet below. It essentially cuts up the array in chunks of size N. Then we use the conditional (ternary) operator to select ifinDirection1
orinDirection2
is the item with the largestAreaCode.length
.If the provided elements are not strictly structured and can be in any order and there are possibly more then two
inDirection
options. I would suggest first grouping all the elements based onRouteId
. Thensort()
each group based onAreaCode.length
in a descending manner and select the first item.The
groupBy()
helper is a helper that returns aMap
instance. In the example aboveRouteId
is used as the key. The value is an array of items that match this key.Both
chunkN()
andgroupBy()
are generic helpers that can be used in lots of other scenarios. You can also achieve the same without helpers (like shown in the two codeblocks below). But defining these helpers separates the thing you want to do (finding the item with the mostAreaCode
s perRouteId
) from the general purpose logic, like grouping or chunking.