在我的扑克应用程序中,我有一排手,每一手都是随机选择的卡片对象,有价值和适合:
[ [ { value: 5, suit: 's' },
{ value: 4, suit: 's' },
{ value: 6, suit: 'c' },
{ value: 11, suit: 'd' },
{ value: 12, suit: 'c' } ],
[ { value: 9, suit: 'd' },
{ value: 12, suit: 'h' },
{ value: 8, suit: 'c' },
{ value: 12, suit: 's' },
{ value: 2, suit: 's' } ],
[ { value: 4, suit: 'h' },
{ value: 6, suit: 's' },
{ value: 10, suit: 'c' },
{ value: 3, suit: 'd' },
{ value: 7, suit: 'd' } ] ]
为了准备评估的手,我想返回一个手对象数组,每个对象都有一个values
和suits
数组。所以输出将是:
[
{
values: [5, 4, 6, 11, 12],
suits: ['s', 's', 'c', 'd', 'c']
},
{
values: [9, 12, 8, 12, 2],
suits: ['d', 'h', 'c', 's', 's']
},
{
values: [4, 6, 10, 3, 7],
suits: ['h', 's', 'c', 'd', 'd']
}
]
我正在尝试使用嵌套的forEach循环来实现这一点,如下所示:
let temp = []
hands.forEach((el) => {
temp = el
el = {}
el.values = []
el.suits = []
temp.forEach((obj) => {
el.values.push(obj.value)
el.suits.push(obj.suit)
console.log(el) //expected output
})
console.log(el) //expected output
})
console.log(hands) //same as original
然而,正如评论所概述的那样,它在循环结束之前表现得如预期,hands
根本没有改变。我在这里缺少什么?
答案 0 :(得分:4)
forEach
不会更改调用它的数组,它只是迭代调用每个元素的函数的数组。如果你想在该函数中构建一个新数组,那就这样做
var newArray = [];
hands.forEach((el) => {
var newValue = // do something here
newArray.push(newValue);
});
我认为你要做的是:
var hands = [ [ { value: 5, suit: 's' },
{ value: 4, suit: 's' },
{ value: 6, suit: 'c' },
{ value: 11, suit: 'd' },
{ value: 12, suit: 'c' } ],
[ { value: 9, suit: 'd' },
{ value: 12, suit: 'h' },
{ value: 8, suit: 'c' },
{ value: 12, suit: 's' },
{ value: 2, suit: 's' } ],
[ { value: 4, suit: 'h' },
{ value: 6, suit: 's' },
{ value: 10, suit: 'c' },
{ value: 3, suit: 'd' },
{ value: 7, suit: 'd' } ] ];
let newValues = []
hands.forEach((el) => {
var temp = {values:[], suits:[]};
el.forEach((obj) => {
temp.values.push(obj.value)
temp.suits.push(obj.suit)
})
newValues.push(temp);
})
console.log(newValues) // NOT same as original

有很多方法可以实现同样的目标,我能想出的最好的方法是 - 并避免在其他答案中看到的双hand.map
(效率非常低)。
var hands = [ [ { value: 5, suit: 's' },
{ value: 4, suit: 's' },
{ value: 6, suit: 'c' },
{ value: 11, suit: 'd' },
{ value: 12, suit: 'c' } ],
[ { value: 9, suit: 'd' },
{ value: 12, suit: 'h' },
{ value: 8, suit: 'c' },
{ value: 12, suit: 's' },
{ value: 2, suit: 's' } ],
[ { value: 4, suit: 'h' },
{ value: 6, suit: 's' },
{ value: 10, suit: 'c' },
{ value: 3, suit: 'd' },
{ value: 7, suit: 'd' } ] ];
let newValues = hands.map(h => {
return h.reduce( (p,c) => {
p.values.push(c.value);
p.suits.push(c.suit);
return p;
},{values:[], suits:[]});
});
console.log(newValues) // NOT same as original

答案 1 :(得分:1)
hands.forEach((el) => {
依次将数组中的每个对象分配给变量el
。
el = {}
您使用对新对象的引用覆盖变量 el
。
el
不再与其原始值相关联。
您只是替换el
的值。数组中的属性仍然指向原始对象。
要更改原始数组中的对象,您需要明确地为它们分配一个新对象。
hands.forEach((originalValue, index, array) => {
// originalValue is what you used to call `temp`
// Just make `el` a new object
var el = {};
// Put it in the array
array[index] = el;
// Then continue as before
答案 2 :(得分:1)
让JavaScript为你做这件事而不是编写大量代码,利用数组支持的map函数:
let rewritten = data.map(hand => {
return {
values: hand.map(card => card.value),
suits: hand.map(card => card.suit),
}
});
(箭头函数中的外部{ return
和}
是不必要的,如果你把它全部放在同一行上,但是对于答案来说,当然它的可读性要低得多)
这将获取您的原始数据,这些数据已经在手上(在这种情况下为三个),然后对每只手应用变换。具体来说,它创建了一个新的对象,其中"值的数组和套装"已经使用map
转换为"只是值",以及#34;只是适合",也使用map
。
JavaScript中的数组带有许多实用程序函数,用于打包/解包/迭代/转换,值得给予读者通过。它们允许你用很少的代码做大事。
如果您在一段时间内或之前没有读过数组API,那么 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array值得一读。它还解释了如何使用recude
,这可以用来提高代码的效率(请参阅Jamiec上面的答案)。
答案 3 :(得分:1)
您可以直接在属性的对象中映射值。
var data = [[{ value: 5, suit: 's' }, { value: 4, suit: 's' }, { value: 6, suit: 'c' }, { value: 11, suit: 'd' }, { value: 12, suit: 'c' }], [{ value: 9, suit: 'd' }, { value: 12, suit: 'h' }, { value: 8, suit: 'c' }, { value: 12, suit: 's' }, { value: 2, suit: 's' }], [{ value: 4, suit: 'h' }, { value: 6, suit: 's' }, { value: 10, suit: 'c' }, { value: 3, suit: 'd' }, { value: 7, suit: 'd' }]],
result = data.map(a => (
{
values: a.map(b => b.value),
suits: a.map(b => b.suit)
})
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
您可以使用较少的迭代样式。
var data = [[{ value: 5, suit: 's' }, { value: 4, suit: 's' }, { value: 6, suit: 'c' }, { value: 11, suit: 'd' }, { value: 12, suit: 'c' }], [{ value: 9, suit: 'd' }, { value: 12, suit: 'h' }, { value: 8, suit: 'c' }, { value: 12, suit: 's' }, { value: 2, suit: 's' }], [{ value: 4, suit: 'h' }, { value: 6, suit: 's' }, { value: 10, suit: 'c' }, { value: 3, suit: 'd' }, { value: 7, suit: 'd' }]],
keys = ['value', 'suit'],
result = data.map(
a => a.reduce(
(r, b) => (keys.forEach(k => r[k + 's'].push(b[k])), r), { values: [], suits: [] }
)
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 4 :(得分:1)
你只需要在第二个循环之前创建一个具有两个属性(值和套装)的对象,并在第二个循环之后将其注入结果:
var hands = [[{ value: 5, suit: 's' }, { value: 4, suit: 's' }, { value: 6, suit: 'c' }, { value: 11, suit: 'd' }, { value: 12, suit: 'c' }], [{ value: 9, suit: 'd' }, { value: 12, suit: 'h' }, { value: 8, suit: 'c' }, { value: 12, suit: 's' }, { value: 2, suit: 's' }], [{ value: 4, suit: 'h' }, { value: 6, suit: 's' }, { value: 10, suit: 'c' }, { value: 3, suit: 'd' }, { value: 7, suit: 'd' }]];
var output = [];
hands.forEach(x => {
var temp = {values: [], suits: []};
x.forEach(y => {
temp.values.push(y.value);
temp.suits.push(y.suit);
})
output.push(temp);
});
console.log(output);