Reputation: 135
I have an array of objects like this:
const jData = [
{
price: "500",
count: "10",
left: "150"
},
{
left: "75",
price: "350",
count: "40"
},
{
count: "200",
left: "50",
price: "7500"
}
];
and array of orderedData like this :
orderedData = ["price", "count", "left"]
I'm trying to sort my array of objects (jData) by keys so that keys will be in the same order as orderedData.
So far my code looks like this:
import "./styles.css";
export default function App() {
const jData = [
{
price: "500",
count: "10",
left: "150"
},
{
left: "75",
price: "350",
count: "40"
},
{
count: "200",
left: "50",
price: "7500"
}
];
const orderedData = ["price", "count", "left"];
let res = jData?.flatMap((x) => Object.keys(x));
var unique = res.filter(function (elem, index, self) {
return index === self.indexOf(elem);
});
const keys = unique?.filter((key) => orderedData.includes(key));
console.log(keys)
let newData = jData.sort(
(a, b) =>
orderedData.indexOf(a) - orderedData.indexOf(b)
)
console.log(newData)
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
I was able to get keys from my array of objects and sort them in the correct order, when I'm console logging keys
console.log(keys); => output is
["price"
1: "count"
2: "left"] // same order as in orderedData = ["price", "count", "left"]
but when I'm trying to sort my jData array so that keys in objects will be positioned in the same order, nothing changes.
let newData = jData.sort(
(a, b) =>
orderedData.indexOf(a) - orderedData.indexOf(b)
)
console.log(newData) => outputs objects with the same positioned keys.
What I would love to achieve is to display objects like this:
const jData = [
{
price: "500",
count: "10",
left: "150"
},
{
price: "350",
count: "40",
left: "75",
},
{
price: "7500"
count: "200",
left: "50",
}
];
I don't know if it's possible to do in Javascript? Thank you for any tip/suggestion.
Upvotes: 1
Views: 1274
Reputation: 960
As @ggorlen suggested, the order of keys in an object is not guaranteed. You could iterate over orderedData
to access the keys from each object in the order you need:
jData.map((item) => (
<ul>
orderedData.map((key) => <li>{key}: {item[key]}</li>)
</ul>
));
Upvotes: 1
Reputation: 56865
Relying on object key order is an antipattern, even when an implementation guarantees insertion order. Objects are traditionally collections of key-value pairs, suitable for lookup by key but not as friendly to iteration or sorting as arrays.
Instead of ordering the object, the general approach to tabular data like this is to provide the array orderedData
alongside the object and, when you need the object's keys in a particular order, map
along orderedData
and key into each column of the row. You can think of orderedData
as headers or column names of the table and jData
as row data.
Here's a proof of concept you can extrapolate to your use case (I realize you're probably not creating the exact component Table
, but it illustrates my point):
const Table = ({rows, columns}) =>
<table>
<tbody>
{columns.map((name, i) =>
<th key={name + i}>{name}</th>
)}
{rows.map((row, i) =>
<tr key={i}>
{columns.map((name, i) =>
<td key={name + i}>{row[name]}</td>
)}
</tr>
)}
</tbody>
</table>
;
const jData = [
{
price: "500",
count: "10",
left: "150"
},
{
left: "75",
price: "350",
count: "40"
},
{
count: "200",
left: "50",
price: "7500"
}
];
const orderedData = ["price", "count", "left"];
ReactDOM.render(
<Table rows={jData} columns={orderedData} />,
document.body
);
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
Upvotes: 0
Reputation: 834
I guess this is the best solution for you. Check this out.
const jData = [
{
price: "500",
count: "10",
left: "150"
},
{
left: "75",
price: "350",
count: "40"
},
{
count: "200",
left: "50",
price: "7500"
}
];
const orderedData = jData.map(x=> {
return Object.entries(x)
.sort(([,a],[,b]) => b-a)
.reduce((r, [k, v]) => ({ ...r, [k]: v }), {});
})
console.log(orderedData)
Upvotes: 1
Reputation: 174
You can try this:
function orderedDataByCustomizedKey(jData,orderedData) {
const newjData = [];
jData.forEach((item, i) => {
const temObj = {};
orderedData.forEach((orderedDataItem, index) => {
temObj[orderedDataItem] = item[orderedDataItem];
})
newjData.push(temObj);
})
return newjData;
}
Upvotes: 1