Увеличение массива через цикл for сохраняет только последний объект? - PullRequest
0 голосов
/ 03 мая 2018

Учитывая мои основные данные такие как:

var data = [
    { name: "Student01", type: "received", grades: [ 12,12, 17, 17, 14.5, 10, 16, 15.5, 15.5, 15 ] },
    { name: "Student02", type: "given", grades: [ 11,6,15, 12 ] },
    { name: "Student03", type: "received", grades: [ 12,12, 17, 17, 14.5, 10, 16, 15.5, 15.5, 15 ]  },
    { name: "Student04", type: "given", grades: [ 12,8,13, 12 ] }
];

Учитывая шаблон объекта , который я должен уважать:

var template = {
  text: "Hello guys !",
  side: "negative",
  name: "Some student",
  x: [ 12.65, 17.92, 16.45 ],
  orientation: "h"
};

Затем я создаю augmentedData через цикл for :

var augmentedData = [];
for (var i=0; i<data.length;i++){
    var trace = template, 
         student = data[i];
    trace.text = "Step "+i;
    trace.name = student.name;
    trace.x    = student.grades;
    console.log(student, student.type)
    trace.side = student.type == "given"?"negative":"positive";
    console.log(vizGrades[i].type, trace, trace.side)
    augmentedData.push(trace);
}

Мои последние дополненные данные состоят из 4-х кратных последнего объекта, сам аугментированный:

console.log(JSON.stringify(augmentedData));

возвращается:

[
  {"text":"Step 3","side":"negative","name":"Student04","x":[12,8,13,12],"orientation":"h"},
  {"text":"Step 3","side":"negative","name":"Student04","x":[12,8,13,12],"orientation":"h"},
  {"text":"Step 3","side":"negative","name":"Student04","x":[12,8,13,12],"orientation":"h"},
  {"text":"Step 3","side":"negative","name":"Student04","x":[12,8,13,12],"orientation":"h"}
];

Что не так? Как это исправить?

РЕДАКТИРОВАТЬ: Ожидаемый результат:

[
  {"text":"Step 0","side":"positive","name":"Student01","x":[12,12, 17, 17, 14.5, 10, 16, 15.5, 15.5, 15],"orientation":"h"},
  {"text":"Step 1","side":"negative","name":"Student02","x":[11,6,15, 12],"orientation":"h"},
  {"text":"Step 2","side":"positive","name":"Student03","x":[12,12, 17, 17, 14.5, 10, 16, 15.5, 15.5, 15],"orientation":"h"},
  {"text":"Step 3","side":"negative","name":"Student04","x":[12,8,13,12],"orientation":"h"}
];

Ответы [ 5 ]

0 голосов
/ 03 мая 2018

Ваша переменная trace является ссылкой на template объект, поэтому всякий раз, когда вы изменяете какое-либо свойство trace, оно также изменяется в ссылочном объекте (template).

Один из способов избежать этой проблемы - переписать ваш код как map операция. Это идеальный вариант использования карты.

Это будет выглядеть примерно так:

const data = [
    { name: "Student01", type: "received", grades: [ 12,12, 17, 17, 14.5, 10, 16, 15.5, 15.5, 15 ] },
    { name: "Student02", type: "given", grades: [ 11,6,15, 12 ] },
    { name: "Student03", type: "received", grades: [ 12,12, 17, 17, 14.5, 10, 16, 15.5, 15.5, 15 ]  },
    { name: "Student04", type: "given", grades: [ 12,8,13, 12 ] }
];

const augmentedData = data.map((student, i) => ({
  text: `Step ${i}`,
  name: student.name,
  x: student.grades,
  side: student.type === "given" ? "negative" : "positive",
}));

console.log(augmentedData);
0 голосов
/ 03 мая 2018

Когда вы делаете var trace = template, вы просто создаете новую переменную, содержащую ссылку на тот же объект.

Вместо создания объекта с именем template вы должны каждый раз создавать новый объект, например:

var data = [
    { name: "Student01", type: "received", grades: [ 12,12, 17, 17, 14.5, 10, 16, 15.5, 15.5, 15 ] },
    { name: "Student02", type: "given", grades: [ 11,6,15, 12 ] },
    { name: "Student03", type: "received", grades: [ 12,12, 17, 17, 14.5, 10, 16, 15.5, 15.5, 15 ]  },
    { name: "Student04", type: "given", grades: [ 12,8,13, 12 ] }
];

var augmentedData = [];
for (var i = 0; i < data.length; i++){
    var student = data[i];

    var trace = {
      text: "Step " + i,
      side: student.type == "given" ? "negative" : "positive",
      name: student.name,
      x: student.grades,
      orientation: "h"
    };

    augmentedData.push(trace);
}

console.log(JSON.stringify(augmentedData));
0 голосов
/ 03 мая 2018

Что не так? Как это исправить?

Написав var trace = template, вы объявляете только ссылку на template объект. При изменении объекта trace, template также будет изменен.

Вам нужна глубокая копия для вашего template объекта. Для этого вы можете использовать метод Object.assign.

Рабочий пример.

var data = [
    { name: "Student01", type: "received", grades: [ 12,12, 17, 17, 14.5, 10, 16, 15.5, 15.5, 15 ] },
    { name: "Student02", type: "given", grades: [ 11,6,15, 12 ] },
    { name: "Student03", type: "received", grades: [ 12,12, 17, 17, 14.5, 10, 16, 15.5, 15.5, 15 ]  },
    { name: "Student04", type: "given", grades: [ 12,8,13, 12 ] }
];

var template = {
  text: "Hello guys !",
  side: "negative",
  name: "Some student",
  x: [ 12.65, 17.92, 16.45 ],
  orientation: "h"
};

var augmentedData = [];
for (var i=0; i<data.length;i++){
    var trace = Object.assign({}, template), 
    student = data[i];
    trace.text = "Step "+i;
    trace.name = student.name;
    trace.x    = student.grades;
    console.log(student, student.type)
    trace.side = student.type == "given"?"negative":"positive";
    augmentedData.push(trace);
}
console.log(JSON.stringify(augmentedData));

Вы можете использовать метод map, передав функцию обратного вызова, чтобы написать более чистое и простое решение для ваших требований.

Кроме того, создайте конструктор объекта с именем template.

var data = [
    { name: "Student01", type: "received", grades: [ 12,12, 17, 17, 14.5, 10, 16, 15.5, 15.5, 15 ] },
    { name: "Student02", type: "given", grades: [ 11,6,15, 12 ] },
    { name: "Student03", type: "received", grades: [ 12,12, 17, 17, 14.5, 10, 16, 15.5, 15.5, 15 ]  },
    { name: "Student04", type: "given", grades: [ 12,8,13, 12 ] }
];
function template(text, side, name, x) {
    this.text = text;
    this.side = side;
    this.name = name;
    this.x = x;
    this.orientation = "h";
}

const augmentedData = data.map((student, i) => 
   new template(`Step ${i}`, student.name, student.grades, student.type === "given" ? "negative" : "positive")
);
console.log(augmentedData);
0 голосов
/ 03 мая 2018

Строка trace = template передает только ссылку на трассировку из шаблона, поэтому вы работаете с одним и тем же объектом в цикле.

Попробуйте

var template = function() {
  return {
    text: "Hello guys !",
    side: "negative",
    name: "Some student",
    x: [ 12.65, 17.92, 16.45 ],
    orientation: "h"
  };
}

Таким образом, trace становится новым объектом каждый раз, используя trace = template();

Fiddle

0 голосов
/ 03 мая 2018

В настоящее время мы ссылаемся на один и тот же объект на каждой итерации и создаем массив одного и того же объекта. Чтобы предотвратить это, нам нужно скопировать содержимое объекта template в объект trace.

Вы можете сделать это с мелкой копией. Есть несколько способов сделать поверхностную копию в Javascript. Я использовал оператор распространения (var trace = {...template}), чтобы скопировать новый шаблон в трассировку.

var data = [
    { name: "Student01", type: "received", grades: [ 12,12, 17, 17, 14.5, 10, 16, 15.5, 15.5, 15 ] },
    { name: "Student02", type: "given", grades: [ 11,6,15, 12 ] },
    { name: "Student03", type: "received", grades: [ 12,12, 17, 17, 14.5, 10, 16, 15.5, 15.5, 15 ]  },
    { name: "Student04", type: "given", grades: [ 12,8,13, 12 ] }
];

var template = {
  text: "Hello guys !",
  side: "negative",
  name: "Some student",
  x: [ 12.65, 17.92, 16.45 ],
  orientation: "h"
};

var augmentedData = [];
for (var i=0; i<data.length;i++){
    var trace = {...template}, 
         student = data[i];
    trace.text = "Step "+i;
    trace.name = student.name;
    trace.x    = student.grades;
    trace.side = student.type == "given"?"negative":"positive";

    augmentedData.push(trace);
}

console.log(JSON.stringify(augmentedData));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...