英文:
Javascript appending object doesn't guarantee order
问题
我看了Stack Overflow上关于JavaScript对象顺序保证的问题。一些人说它们保证,而一些人说它们不保证,具体取决于情况。与此同时,我遇到了以下问题。
我有一个类似以下的对象数组:
const arrayObject = [
{ id: 'a123', bar: 'hello' },
{ id: 'a321', bar: 'foo' }
];
现在我希望将这个arrayObject
转换成对象的对象,结构如下,并且与数组的顺序相同:
const object = {
'a123': { id: 'a123', bar: 'hello' },
'a321': { id: 'a321', bar: 'foo' }
}
基本上使用数组中每个项目的id
作为对象的键。以下是我尝试实现此目标的代码:
let newObj = {};
arrayObject.forEach(data => {
const temp = {
[data.id]: {
id: data.id,
bar: data.bar
},
};
newObj = { ...newObj, ...temp };
})
我确实得到了正确的结构,但顺序与arrayObject
的顺序不同,即它返回:
const object = {
'a321': { id: 'a321', bar: 'foo' },
'a123': { id: 'a123', bar: 'hello' }
}
我尝试了数组中更多的项目,但结果相同。它不保证顺序。
我的代码有什么问题,还是它根本不保证顺序?
我该如何使对象的顺序与数组相同?
英文:
I have looked at this question in stack overflow about objects guaranteeing order.
https://stackoverflow.com/questions/5525795/does-javascript-guarantee-object-property-order
some says they guarantee, some says they don't, depending on situations. Meantime I've encountered following problem.
I have an array of objects, similar to below:
const arrayObject = [
{id:'a123', bar:'hello'},
{id:'a321', bar: 'foo'} ];
now I wish to turn this arrayObject into object of object, with structure as follows with the same order as the array:
const object = {
'a123': {id:'a123', bar:'hello'},
'a321': {id:'a321', bar: 'foo'},
}
basically using the id of each item in the array as the key of the object. Below is the code I used to try to achieve it:
let newObj = {};
arrayObject.forEach(data=>{
const temp = {
[data.id]:{
id: data.id,
bar: data.bar
},
};
newObj={...newObj, ...temp};
})
I do get the correct structure, however the order is not the same as the order of arrayObject, i.e. it returns:
const object = {
'a321': {id:'a321', bar: 'foo'},
'a123': {id:'a123', bar:'hello'},
}
I've tried with more items in the array, and I get same result. It does not guarantee the order.
Is there something wrong with my code, or is it simply not guaranteeing the order?
What do I have to do to make the object be the same order as the array?
答案1
得分: 3
保留顺序,通过在(无序的)对象中包含排序信息。随时需要恢复原始顺序时,请使用保存的排序信息...
const arrayObject = [{
id: 'a123',
bar: 'hello'
},
{
id: 'a321',
bar: 'foo'
}
];
let object = {}
arrayObject.forEach((e, i) => {
object[e.id] = { ...e, orderWith: i } // the index will tell us how to sort later
})
// later on
let sorted = Object.values(object).sort((a, b) => a.orderWith - b.orderWith)
console.log(sorted)
英文:
Preserve the order by including ordering information in the (unordered) object. Anytime later, when you need to recover the original order, use the saved ordering information...
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const arrayObject = [{
id: 'a123',
bar: 'hello'
},
{
id: 'a321',
bar: 'foo'
}
];
let object = {}
arrayObject.forEach((e, i) => {
object[e.id] = { ...e, orderWith: i } // the index will tell us how to sort later
})
// later on
let sorted = Object.values(object).sort((a, b) => a.orderWith - b.orderWith)
console.log(sorted)
<!-- end snippet -->
答案2
得分: 1
我认为你正在寻找的是一个Map()
对象。请参见这里 -> Map and Set
const arrayObject = [
{id: 'a123', bar: 'hello'},
{id: 'a321', bar: 'foo'},
{id: 'a234', bar: 'more'},
{id: 'a735', bar: 'words'},
{id: 'a167', bar: 'added'},
{id: 'a857', bar: 'now'},
];
var newObj = new Map();
for (var i=0; i<arrayObject.length; i++) {
const temp = {
id: arrayObject[i].id,
bar: arrayObject[i].bar
};
newObj.set(arrayObject[i].id, temp);
}
var jsonText = JSON.stringify(Array.from(newObj.entries()));
console.log(jsonText);
// 要获取元素,请使用 .get()
console.log(newObj.get("a321").bar);
英文:
I think what you're looking for is a Map()
object. See here -> Map and Set
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const arrayObject = [
{id:'a123', bar:'hello'},
{id:'a321', bar: 'foo'},
{id:'a234', bar: 'more'},
{id:'a735', bar: 'words'},
{id:'a167', bar: 'added'},
{id:'a857', bar: 'now'},
];
var newObj = new Map();
for (var i=0; i<arrayObject.length; i++) {
const temp = {
id: arrayObject[i].id,
bar: arrayObject[i].bar
};
newObj.set(arrayObject[i].id, temp);
}
var jsonText = JSON.stringify(Array.from(newObj.entries()));
console.log(jsonText);
// To get at the elements, use .get()
console.log(newObj.get("a321").bar);
<!-- end snippet -->
答案3
得分: 0
以下是翻译的代码部分:
一个更简单的代码示例如下(使用 `for` 循环而不是 `forEach`):
let newObj = {};
for (const data of arrayObject) {
newObj[data.id] = data;
}
这可能会得到您想要的结果,因为它将保证对象构建的顺序与数组中的顺序相匹配。使用 forEach
会导致多个函数以它们运行的任何顺序被调用,这可能是无序的。但要注意,即使使用 for 循环也不能保证顺序始终匹配。一个 Array
会保证顺序,但以这种方式创建的对象不会。即使上面的代码目前提供了所需的顺序,将来也可能不会如此。如果需要保留顺序,请使用 Array
。
<details>
<summary>英文:</summary>
A simpler bit of code would be like this (use a `for` loop instead of `forEach`:
let newObj = {};
for (const data of arrayObject) {
newObj[data.id] = data;
}
This might get you what you want because it will guarantee that the order the object is built matches the order in the array. Using `forEach` causes multiple functions to be called in whatever order they run, which might be out of order. But realize that even using the for-loop *does not guarantee the order will always match*. An `Array` will guarantee the order, but the Object made this way does not. Even if the above code does give you the desired order, it might not in the future. Use an `Array` if you need to preserve order.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论