I have an object that looks like below
const tableData = [
{
"Location": "London",
"Status": "Unknown"
},
{
"Location": "Delhi",
"Status": "Reachable"
},
{
"Location": "Berlin",
"Status": "Unknown"
},
{
"Location": "Tokyo",
"Status": "Busy"
},
]
Now I want to create a 2D array which will hold this information in a certain way. Here is my code below
const statusOrder = {"Reachable": 0, "Busy": 1, "Unknown": 2}
let statusOrderInfo = Array(Object.keys(statusOrder).length).fill([]);
for(let i=0; i< tableData.length; i ) {
const status = tableData[i]["Status"].trim()
const statusIndex = statusOrder[status]
statusOrderInfo[statusIndex].push(tableData[i])
}
console.log(statusOrderInfo)
As you can see I want each item of the tableData
object to be in a certain index of the 2D array. So the item that contains Status
as Reachable
should be at index 0, the item that contains the Status
as Busy
should be at index 1 and so on.
So the final output should look like
[
[
{
"Location":"Delhi",
"Status":"Reachable"
}
],
[
{
"Location":"Tokyo",
"Status":"Busy"
}
],
[
{
"Location":"London",
"Status":"Unknown"
},
{
"Location":"Berlin",
"Status":"Unknown"
}
]
]
But I get a wrong output on running the above code even though I am targeting the correct index. What's wrong in my approach?
CodePudding user response:
Using Array#reduce
:
const
tableData = [ { "Location": "London", "Status": "Unknown" }, { "Location": "Delhi", "Status": "Reachable" }, { "Location": "Berlin", "Status": "Unknown" }, { "Location": "Tokyo", "Status": "Busy" } ],
statusOrder = {"Reachable": 0, "Busy": 1, "Unknown": 2};
const statusOrderInfo = tableData.reduce((list, e) => {
const index = statusOrder[e.Status];
list[index] = [...(list[index] || []), {...e}];
return list;
}, []);
console.log(statusOrderInfo);
CodePudding user response:
Simple fix on your problem is that just changing your manner to set initial value of statusOrderInfo
and use Array.from
instead of Array.fill
like this:
let statusOrderInfo = Array.from({length: Object.keys(statusOrder).length}, ()=> []);
another solution is set initiali value of statusOrderInfo
by empty array, and then in your for loop, after you get the index of current object based on status
value, you can check if statusIndex
already exist in the statusOrderInfo
or not, like this:
const statusOrder = {"Reachable": 0, "Busy": 1, "Unknown": 2}
let statusOrderInfo = [];
for(let i=0; i< tableData.length; i ) {
const status = tableData[i]["Status"].trim()
const statusIndex = statusOrder[status];
if(statusOrderInfo[statusIndex]) statusOrderInfo[statusIndex].push(tableData[i]);
else statusOrderInfo[statusIndex] = [ tableData[i] ]
}
console.log(statusOrderInfo);
another solution, is to use reduce
method on array, like this:
const tableData = [{
"Location": "London",
"Status": "Unknown"
},
{
"Location": "Delhi",
"Status": "Reachable"
},
{
"Location": "Berlin",
"Status": "Unknown"
},
{
"Location": "Tokyo",
"Status": "Busy"
},
];
const statusOrder = {"Reachable": 0, "Busy": 1, "Unknown": 2}
const result = tableData.reduce((acc, cur) => {
const index = statusOrder[cur.Status];
if (acc[index]) acc[index].push(cur);
else acc[index] = [cur]
return acc;
}, []);
console.log(result)
CodePudding user response:
Anoter one solution in kind of declartive way:
First of all sort objects by status code using Array#sort
And then just wrap every object to it own array using Array#map
const tableData = [{Location: "London",Status: "Unknown"},{Location: "Delhi",Status: "Reachable"},{Location: "Berlin",Status: "Unknown"},{Location: "Tokyo",Status: "Busy"}]
const statusOrder = {Reachable: 0, Busy: 1, Unknown: 2}
const result = tableData
.sort(({ Status: s1 }, { Status: s2 }) => statusOrder[s1] - statusOrder[s2])
.map((item) => [item]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
CodePudding user response:
As others explained, reduce would be the best choice for your scenario. Because on every iteration you would create a new Array object.
const tableData = [{ Location: "London", Status: "Unknown" }, { Location: "Delhi", Status: "Reachable" }, { Location: "Berlin", Status: "Unknown" }, { Location: "Tokyo", Status: "Busy" }]
const statusOrder = { "Reachable": 0, "Busy": 1, "Unknown": 2 };
const statusOrderInfo = tableData.reduce((accumulator, currentValue) => {
const index = statusOrder[currentValue.Status];
if (accumulator[index]) {
accumulator[index].push(currentValue);
} else {
accumulator[index] = [currentValue];
}
return accumulator;
}, []);
console.log(statusOrderInfo);
Explanation for what's going on in your code:
As you have used [].fill([])
to fill the Array. It would create only one empty Array object and use it to initialize the actual array. That's why the following snippet behaves the way it should behave :)
const statusOrderInfo = Array(3).fill([]);
statusOrderInfo[0].push(10);
console.log(statusOrderInfo);
/* Results:
[
[ 10 ],
[ 10 ],
[ 10 ]
]
*/