В Javascript, как я могу сказать array.filter () дублировать объекты элементов в новом массиве? - PullRequest
1 голос
/ 24 сентября 2019

Итак, упрощенный код.

var a = [
    { name: "first", num: 1 },
    { name: "first", num: 2 },
    { name: "first", num: 3 },
    { name: "first", num: 4 },
    { name: "first", num: 5 },
    { name: "first", num: 6 },
    { name: "first", num: 7 },
    { name: "first", num: 8 },
    { name: "first", num: 9 }
];

var b = a.filter(function(el) {
    return el.num % 2 == 0;
});

console.log("a1", a); // [1, 20, 3, 40, 5, 60, 7, 80, 9]
console.log("b1", b); // [20, 40, 60, 80]

for (let i = 0; i < b.length; i++) {
    b[i].num = b[i].num * 10;
}

console.log("a2", a); // [1, 20, 3, 40, 5, 60, 7, 80, 9]
console.log("b2", b); // [20, 40, 60, 80]

Мое новое понимание состоит в том, что элемент массива содержит ссылку на объект, а не объект.Как можно дублировать эти объекты?

  1. Фильтровать, затем строить новые объекты из отфильтрованного массива и помещать новые объекты в новый массив?
  2. Использовать какой-то метод I 'Вы не знакомы с?
  3. Перепроектировать код, чтобы прекратить использовать объекты в массиве?

Кроме того, что случилось с console.log (), показывающим, что переменные изменились при размещении доцикл for?

Ответы [ 5 ]

1 голос
/ 24 сентября 2019

Если вы хотите клонировать объекты, вам понадобится функция клонирования, я использую эту функцию

const clone = obj =>
  Array.isArray(obj)
    ? obj.map(item => clone(item))
    : obj instanceof Date
    ? new Date(obj.getTime())
    : obj && typeof obj === 'object'
    ? Object.getOwnPropertyNames(obj).reduce((o, prop) => {
        o[prop] = clone(obj[prop]);
        return o;
      }, {})
    : obj;

Затем вы можете клонировать массив с помощью

let c = clone(b);

, что будет новыммассив, в котором каждый объект является новым клоном.

var a = [{name: 'first', num:1}, {name:'first', num: 2}, {name:'first', num: 3}, 
   {name:'first', num: 4}, {name:'first', num: 5}, {name:'first', num: 6}, {name:'first', num: 7}, 
   {name:'first', num: 8}, {name:'first', num: 9}];

var b = a.filter(function(el){return el.num%2==0 });
   
 const clone = obj =>
    Array.isArray(obj)
      ? obj.map(item => clone(item))
      : obj instanceof Date
      ? new Date(obj.getTime())
      : obj && typeof obj === 'object'
      ? Object.getOwnPropertyNames(obj).reduce((o, prop) => {
          o[prop] = clone(obj[prop]);
          return o;
        }, {})
      : obj;

 let c = clone(b);
 
 console.log(b[0] === c[0]);
1 голос
/ 24 сентября 2019

Если вы хотите дублировать объекты внутри массива, вы должны использовать функцию map.

var b = a.filter(val => val.num %2 === 0).map(val => Object.assign({}, val, { num: val.num * 10}));

Функция map вернет новый массив со значением, возвращенным из функции.В этом примере мы создаем новый объект Object.assign({}) и дублируем существующий объект при изменении поля num.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

0 голосов
/ 24 сентября 2019

Если вам нужен новый массив с конечными значениями, который вы можете использовать, чтобы уменьшить, чтобы сделать все это за один раз, то уменьшение запускается с накопителем пустого массива и при каждой итерации, если оно удовлетворяет условию, добавляется клон с оператором распространения.переопределение числа num 10.

var a = [{name: 'first', num:1}, {name:'first', num: 2}, {name:'first', num: 3}, 
   {name:'first', num: 4}, {name:'first', num: 5}, {name:'first', num: 6}, {name:'first', num: 7}, 
   {name:'first', num: 8}, {name:'first', num: 9}];

const evensTimes10 = array => array.reduce((results, item) => {
  if (item.num % 2 === 0) {
    results.push({ ...item, num: item.num * 10 });
  }
  return results;
}, []);


var b = evensTimes10(a);

console.log('a1',a); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log('b1',b); // [20, 40, 60, 80]
0 голосов
/ 24 сентября 2019

Простое решение с использованием некоторого синтаксиса ES6:

var a = [{name: 'first', num:1}, {name:'first', num: 2}, {name:'first', num: 3}, 
{name:'first', num: 4}, {name:'first', num: 5}, {name:'first', num: 6}, {name:'first', num: 7}, 
{name:'first', num: 8}, {name:'first', num: 9}];

const b = a
.filter(el => {
    if (el.num % 2 === 0) {
        return {
            ...el
        }
    }
})
.map(newEl => newEl.num * 10);

console.log('a', a);  // [1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log('b', b);
  1. .filter () выполняет итерацию массива "a" и возвращает только элементы со свойством "num", которое достигает условия.Это клонированный массив.
  2. return { ...el } возвращает клонированный объект благодаря оператору распространения.
  3. .map () создает новый массив и возвращает каждое значение "el.num" * 10

Вот некоторая информация о .map () .filter () и операторе спреда:

Я нашел этот очень интересный сайт, который перечисляет все функции Javascript с их описаниями и показывает, является ли изменяемый или нет, это очень помогает: https://doesitmutate.xyz/

0 голосов
/ 24 сентября 2019

Да, элементы массива a являются указателями .поэтому вам нужно использовать Object.assign (как говорят многие)

и другое решение с использованием массива, уменьшающее использование (см. комментарий бренда Adrian)

var a = [ { name: 'first', num: 1 } 
        , { name: 'first', num: 2 } 
        , { name: 'first', num: 3 } 
        , { name: 'first', num: 4 } 
        , { name: 'first', num: 5 } 
        , { name: 'first', num: 6 } 
        , { name: 'first', num: 7 } 
        , { name: 'first', num: 8 } 
        , { name: 'first', num: 9 } 
        ] 

var b = a.filter(el=>!(el.num%2)).map(el=>Object.assign({},el))

// other solution with reduce 

var c = a.reduce((acc,cur)=>{
  if (!(cur.num%2) )acc.push(Object.assign({},cur))
  return acc
}, [])

ConsoleArrayNamNum('var a -1-',a)  // [1,2,3,4,5,6,7,8,9]
ConsoleArrayNamNum('var b -1-',b)  // [2, 4, 6, 8]
ConsoleArrayNamNum('var c -1-',c)  // [2, 4, 6, 8]

for(let elm of b)
  { elm.num *= 10 }

ConsoleArrayNamNum('var a -2-',a)  // [1,2,3,4,5,6,7,8,9]
ConsoleArrayNamNum('var b -2-',b)  // [20, 40, 60, 80]


function ConsoleArrayNamNum(title,arr) {
  console.log(title)
  for(let elm of arr)
    { console.log(`{ name: '${elm.name}', num: ${elm.num} }`) }
}
.as-console-wrapper { min-height: 100% !important; }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...