Проблема создания массива объектов

1

У меня есть массив, и я хочу выбрать 3 его элемента и поместить его в другой массив как один объект и снова повторно следовать одному и тому же процессу на каждые 3 элемента массива. Это мой код ниже:

let breakpoints = [
  {name: "from-amonut", value: "100"},
  {name: "to-amonut", value: "200"},
  {name: "gst", value: "10"},
  {name: "from-amonut", value: "200"},
  {name: "to-amonut", value: "300"},
  {name: "gst", value: "20"},
  {name: "from-amonut", value: "300"},
  {name: "to-amonut", value: "400"},
  {name: "gst", value: "30"}
];

let temp = {
  "from_amount": 0,
  "to_amount": 0,
  "gst": 0
};

let formattedBreakpoints = [];

breakpoints.map((v, k) => {
  (v.name == "from-amonut") ? temp.from_amount = v.value: "";
  (v.name == "to-amonut") ? temp.to_amount = v.value: "";
  (v.name == "gst") ? temp.gst = v.value: "";
  ((k + 1) % 3 === 0) ? (formattedBreakpoints.push(temp), console.log(temp)) : "";

});
console.log(formattedBreakpoints);

Я ожидаю formattedBreakpoints быть [{"from_amount":100, "to_amount":200, "gst":10}, {"from_amount":200, "to_amount":300, "gst":20}.....] но возвращает только все объекты со значением последних элементов массива.

  • 0
    Ваш массив результатов состоит из ссылок на один и тот же объект.
Теги:
ecmascript-6
object
arrays

3 ответа

2
Лучший ответ

Вы можете использовать Array.reduce() чтобы добавить все свойства к последнему объекту. Всякий раз, когда индекс (i) остается от 3, равен 0, вы добавляете еще один объект к аккумулятору.

const breakpoints = [{"name":"from-amonut","value":"100"},{"name":"to-amonut","value":"200"},{"name":"gst","value":"10"},{"name":"from-amonut","value":"200"},{"name":"to-amonut","value":"300"},{"name":"gst","value":"20"},{"name":"from-amonut","value":"300"},{"name":"to-amonut","value":"400"},{"name":"gst","value":"30"}];
        
const result = breakpoints.reduce((r, { name, value }, i) => {
  if(i % 3 === 0) r.push({});
  
  const key = name.replace(/-/g, '_');

  r[r.length - 1][key] = value;
  
  return r;
}, []);

console.log(result);

Какая проблема в вашем коде является повторное использование temp. Поскольку temp является объектом, толкает его в массив, добавляет ссылку на массив и не создает новый объект. Чтобы этого избежать, вы можете инициализировать temp всякий раз, когда вы добираетесь до последнего свойства. Вы также должны использовать Array.forEach() (сделать что-то со значением) вместо Array.map() (создать новый массив с элементами на основе исходных значений).

const breakpoints = [{"name":"from-amonut","value":"100"},{"name":"to-amonut","value":"200"},{"name":"gst","value":"10"},{"name":"from-amonut","value":"200"},{"name":"to-amonut","value":"300"},{"name":"gst","value":"20"},{"name":"from-amonut","value":"300"},{"name":"to-amonut","value":"400"},{"name":"gst","value":"30"}];

let temp = {};

const formattedBreakpoints = [];

breakpoints.forEach((v, k) => {
  if(v.name == "from-amonut") temp.from_amount = v.value;
  if(v.name == "to-amonut") temp.to_amount = v.value;
  if(v.name == "gst") { // whenever we get to gst, we can push to array, and reset temp
    temp.gst = v.value;
    formattedBreakpoints.push(temp);
    temp = {};
  };
});
console.log(formattedBreakpoints);
  • 0
    Огромное спасибо. Это работает! Но не могли бы вы сказать мне, что не так с моим кодом?
  • 0
    @zainulabdeen - см. обновленный ответ.
Показать ещё 2 комментария
2

Проблема с вашим кодом в том, что вы мутируете одну временную температуру объекта и нажимаете ее 3 раза на массив результатов. Итак, что происходит:

  1. Вы создаете объект
  2. В методе карты вы мутируете его несколько раз, и после каждых 3 итераций вы устанавливаете ссылку на этот объект на массив результатов.

Ключевое слово здесь - reference. Это означает, что это тот же объект. Например:

const result = [];
const obj = {};

obj.a = 'a';
result.push(obj); // => result = [{ a: 'a' }]

obj.b = 'b';
result.push(obj); // => result = [{ a: 'a', b: 'b' }, { a: 'a', b: 'b' }]

Попробуйте так:

let formattedBreakpoints = [];
for (let i = 0; i < breakpoints.length; i += 3) {
  const breakPointOptions = breakpoints.slice(i, i + 3);
  formattedBreakpoints.push(breakPointOptions.reduce((result, { name, value }) => {
    result[name] = value;
    return result;
  }, {}));
}
  • 0
    Это работает! Но не могли бы вы сказать мне, что не так с моим кодом?
  • 0
    @zainulabdeen добавил подробное объяснение
Показать ещё 3 комментария
1

let breakpoints = [
    			{name: "from-amonut", value: "100"},
    			{name: "to-amonut", value: "200"},
    			{name: "gst", value: "10"},
    			{name: "from-amonut", value: "200"},
    			{name: "to-amonut", value: "300"},
    			{name: "gst", value: "20"},
    			{name: "from-amonut", value: "300"},
    			{name: "to-amonut", value: "400"},
    			{name: "gst", value: "30"}
    		]
    		let temp = {
    			"from_amount" : 0,
    			"to_amount" : 0,
    			"gst" : 0
    		};
    		let formattedBreakpoints = [];
    		breakpoints.map((v, k)=>{
    			(v.name == "from-amonut") ? temp.from_amount = v.value : "";
    			(v.name == "to-amonut") ? temp.to_amount = v.value : "";
    			(v.name == "gst") ? temp.gst = v.value : "";
    			((k + 1) % 3 === 0) ? (formattedBreakpoints.push(temp), temp = {... temp}) : "" ;
    			
    		});
    		console.log(formattedBreakpoints);

Поскольку temp является объектом, вы используете его по ссылке. Поэтому вам нужно создавать новый объект каждый раз, когда вы нажимаете, или же на него ссылается тот же объект. Поэтому я использую temp для создания этого нового объекта.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню