Cześć chcę wiedzieć, jak mogę osiągnąć to podejście: mam tę tablicę obiektów:

const array =[{district:1,buildings:["1","2"]},{district:1,buildings:["1","3"]},{district:2,buildings:["1","2"]}]

Chcę scalić obiekty tablicy + scalenie budynków obiektu z tą samą dzielnicą.

Co powinienem dostać:

const array =[{district:1,buildings:["1","2","3"]},{district:2,buildings:["1","2"]}]

Jakaś pomoc. dzięki

Uwaga: można to zrobić za pomocą pętli for, ale szukam prostszego podejścia.

1
adel 1 kwiecień 2020, 13:18

4 odpowiedzi

Najlepsza odpowiedź

To rozwiązanie, które:

  • nie nadpisuje / nie zmienia oryginalnej tablicy
  • jest w pełni sprawny

Wyjaśnienie:

  1. Użyj array.reduce(..), aby zredukować listę tylko do dwóch unikalnych wpisów (dzielnica 1 i 2), z których każdy ma (prawdopodobnie) nieunikalną listę budynków.
  2. Użyj Object.entries(..).map(..), aby móc iterować dzielnice w celu nadania budynkowi wyjątkowości.
 const array = [
  { district: 1, buildings: [ '1', '2' ] },
  { district: 1, buildings: [ '1', '3' ] },
  { district: 2, buildings: [ '1', '2' ] }
];
 
 const result = Object.entries(
  array.reduce(
    (acc, {district, buildings}) => {
        acc[district] = acc[district] ? acc[district] : []; 
        acc[district].push(...buildings);
        return acc;
    }, 
    []
  )
).map(m => ({district: parseInt(m[0]), buildings: [...new Set(m[1])]}));

console.log(result);
2
Simon 1 kwiecień 2020, 11:17

Możesz użyć Array.prototype.reduce, aby utworzyć obiekt, który będzie przechowywać wszystkie wartości dla określonej dzielnicy (dzielnica będzie kluczami)

Następnie będziesz mieć obiekt z kluczami jako dzielnicami i wartością jako tablicą budynku. Następnie możesz odtworzyć tablicę za pomocą Array.prototype.map i ustawić usuwanie duplikatów.

const array = [{
    district: 1,
    buildings: ["1", "2"]
  },
  {
    district: 1,
    buildings: ["1", "3"]
  },
  {
    district: 2,
    buildings: ["1", "2"]
  }
];

let mapped_array = array.reduce((acc, val) => {
  acc[val.district] = acc[val.district] ?
    acc[val.district].concat(val.buildings) :
    val.buildings;
  return acc;
}, {});

mapped_array = Object.keys(mapped_array).map(val => {
  return {
    district: val,
    buildings: [...new Set(mapped_array[val])]
  };
});

console.log(mapped_array);
1
Akshay Bande 1 kwiecień 2020, 11:01

Możesz to zrobić w ten sposób:

const array = [{district:1,buildings:["1","2"]},{district:1,buildings:["1","3"]},{district:2,buildings:["1","2"]}];

function merge(arr){

  let result = [];
  
   arr.forEach(item => {
    if(result[item.district]){
       item.buildings.forEach(val => {result[item.district].add(val)});
    } else {
       result[item.district] = new Set(item.buildings);
    }
  })
  
  return result.filter(item => item).map((item,i) => {return {district: i + 1, buidings: [...item]}});

}

console.log(merge(array));
0
Leonid 1 kwiecień 2020, 10:50

Pętle są dobre, ale oto podejście wykorzystujące kilka wbudowanych metod:

const array =[{district:1,buildings:["1","2"]},{district:1,buildings:["1","3"]},{district:2,buildings:["1","2"]}]

var result = {}; //will store our results, object/dict used for optimal indexing
array.map(function(row){ //for each row in the array
    //if we have no existing record of it, we will store that record
   if(!result[row.district])result[row.district]=row;
   else{
      //since we have an existing record we will modify it
      //for each building num in the new record
      row["buildings"].map(function(buildingNum){
            //if the building number doesn't exist in the existing record
           if(result[row.district]['buildings'].indexOf(buildingNum)==-1){
               result[row.district]['buildings'].push(buildingNum) //add it
           }
      })

   }
})
result=Object.values(result) //convert our result back to an array
0
ggordon 1 kwiecień 2020, 11:02