更改两个数组也始终更改另一个数组

时间:2017-04-04 04:51:52

标签: javascript arrays node.js

对于项目,我需要导入Excel文件,将数据更改为JSON,并以不同的方式重新格式化,以便我的应用程序可读。一步是将Excel的一行拆分为两个不同的数组,这些数组必须单独更改。

但无论我做错了什么 - 对其中一个数组的任何更改不仅会相应地更改另一个数组,还会更改我的原始数据。



let data = [{
  value1: 1,
  value2: 2
}, {
  value1: 3,
  value2: 4
}]
let temp1 = [];
let temp2 = [];
for (let x of data) {
  temp1.push(x); //pushing x in array 1
  temp2.push(x); //pushing x as well in array 2
}
for (let x of temp1) {
  x.type = 'typeA'
}
for (let x of temp2) {
  x.type = 'typeB'
}
console.log(JSON.stringify(data));
console.log(JSON.stringify(temp1));
console.log(JSON.stringify(temp2));
//all three give the same result.




有人知道我的代码出错了吗?

4 个答案:

答案 0 :(得分:3)

Javascript数组是基于引用的 - 因此您可以将其视为包含对相同值的引用的数组1和数组2。更改一个数组中的值将在另一个数组中更改它,因为它们无论如何都是相同的基础。

您真正需要的是如何深度克隆值。这是一个如何解决这个限制的例子。



let data = [{
  value1: 1,
  value2: 2
}, {
  value1: 3,
  value2: 4
}]
let temp1 = [];
for (let x of data) {
  temp1.push(x); //pushing x in array 1
}
  
// This is one of the "workaround ways" of constructing
// an array of fresh values (otherwise known as deep cloning).
// this doesn't work in cases where you might have cyclic javascript
// objects or functions, but works if you're dealing with JSON values.
let temp2 = JSON.parse(JSON.stringify(temp1));

for (let x of temp1) {
  x.type = 'typeA'
}
for (let x of temp2) {
  x.type = 'typeB'
}
console.log(JSON.stringify(data));
console.log(JSON.stringify(temp1));
console.log(JSON.stringify(temp2));
//all three give the same result.




由于您实际上知道您的数据是对象列表,因此可以使用。在实践中,你可能想要使用更健壮的东西...比如lodash的cloneDeep:https://lodash.com/docs/4.17.4#cloneDeep

答案 1 :(得分:1)

数据是此处定义的唯一对象,您只是在进行引用并将数据推送到其他数组,

看看这些片段是如何运作的

var x = {};
var y = x;
y.age = 10;
console.log("x is :",x);
//{age:10;}
var a = [];
var b = a;
b.push(10);
console.log("a is :",a);
//[10]

答案 2 :(得分:1)

在您的问题中,您looping the data objects并将其每个值分配给临时值,因此memory location中的same as of data将是JSON.parse(JSON.stringify(data))

因此,让for (let x of JSON.parse(JSON.stringify(data))) { temp1.push(x); //pushing x in array 1 temp2.push(x); //pushing x as well in array 2 } 更改内存位置并将其循环,

更改,

let data = [{
  value1: 1,
  value2: 2
}, {
  value1: 3,
  value2: 4
}]
let temp1 = [];
let temp2 = [];
for (let x of JSON.parse(JSON.stringify(data))) {
  temp1.push(x); //pushing x in array 1
  temp2.push(x); //pushing x as well in array 2
}
temp1 = JSON.parse(JSON.stringify(temp1))
for (let x of temp1) {
  x.type = 'typeA'
}
temp2 = JSON.parse(JSON.stringify(temp2))
for (let y of temp2) {
  y.type = 'typeB'
}
console.log(JSON.stringify(data));
console.log(JSON.stringify(temp1));
console.log(JSON.stringify(temp2));
//all three give the same result.

# Libraries: stringr to extract the years and months,
# dplyr and tidyr for pipe operations
library(stringr)
library(dplyr)
library(tidyr)

df = read.table(text=tab, header=TRUE)
df = df %>%
    mutate(
        year = as.numeric(str_sub(YearMonth, 1, 4)),
        month = as.numeric(str_sub(YearMonth, 5, 6))
    ) %>%
    arrange(Client_ID, year, month) %>%
    group_by(Client_ID) %>%
    mutate(decline = c(FALSE, diff(Amount) < 0),
           # Look at 2 upcoming rows and see if there was a decline in
           # both of them
           decline3 = (lead(decline, 1, default=FALSE) & lead(decline, 2, default=FALSE)))

请运行以上代码段

答案 3 :(得分:1)

datatemp1temp2确实是三个不同的数组,但temp1temp2中的项只是对{ data数组中的项目,因此它们都只是引用相同的对象。因此,更改一个数组中的对象将影响其他数组。

您可以做的不是运行temp1.push(x)temp2.push(x),而是push代替x对象的副本。这可以这样做:

temp1.push(Object.assign({}, x));
temp2.push(Object.assign({}, x));

这样,三个数组中包含的项目将是唯一对象,而不仅仅是对相同对象的引用。