Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/451.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/33.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 将数组按多个字段分组_Javascript_Angular - Fatal编程技术网

Javascript 将数组按多个字段分组

Javascript 将数组按多个字段分组,javascript,angular,Javascript,Angular,我有一个api响应,如下所示: people = [ { name: 'John', surname: 'Doe', pet: { type: 'CAT', name: 'whiskers', age: 1 } }, { name: 'John', surname: 'Doe', pet: { type: 'DOG

我有一个api响应,如下所示:

people = [
    {
      name: 'John',
      surname: 'Doe',
      pet: {
          type: 'CAT',
          name: 'whiskers',
          age: 1
      }
    },
    {
      name: 'John',
      surname: 'Doe',
      pet: {
        type: 'DOG',
        name: 'Dexter',
        age: 4
      }
    },
    {
      name: 'Jane',
      surname: 'Doe',
      pet: {
        type: 'CAT',
        name: 'Fluffy',
        age: 10
      }
    },
    {
      name: 'Jane',
      surname: 'Doe',
      pet: {
        type: 'CAT',
        name: 'Dennis',
        age: 3
      }
    }
  ]
我想把它翻译成这样(只有两种宠物):

我用的是角度5。我需要能够显示一张类似以下内容的表格:

<table>
  <thead>
  <tr>
    <th>Name</th>
    <th>Surname</th>
    <th>Cats</th>
    <th>Dogs</th>
  </tr>
  </thead>
  <tbody>
  <tr *ngFor="let person of people">
    <td>{{person.name}}</td>
    <td>{{person.surname}}</td>
    <td>
      <ul>
        <li *ngFor="let cat of person.cats">name: {{cat.name}}, age: {{cat.age}} years</li>
      </ul>
    </td>
    <td>
      <ul>
        <li *ngFor="let dog of person.dogs">name: {{dog.name}}, age: {{dog.age}} years</li>
      </ul>
    </td>
  </tr>
  </tbody>
</table>

理想情况下,我将被允许更改api,以便此逻辑位于服务器端。同时,我想知道如何做到这一点。

您可以使用
reduce
将数据汇总到一个对象。使用
Object.values
将对象转换为数组

let people=[{姓名:'John',姓氏:'Doe',宠物:{类型:'CAT',姓名:'胡须',年龄:1}},{姓名:'John',姓氏:'Doe',宠物:{类型:'DOG',姓名:'Dexter',年龄:4},{姓名:'Jane',姓氏:'Dennis',宠物:{类型:'CAT',姓名:'Fluffy',年龄:10},{姓名:'Jane',姓氏:'Doe',宠物:{类型:'CAT',姓氏:'Dennis',年龄:3}];
让result=Object.values(people.reduce((c,{pet,{u})=>{
让k=u.name+u.姓氏;//使用name和last name制作一个键
让{type,…p}=pet;//解构pet对象
type=type.toLowerCase();//使类型小写
c[k]=c[k]| | u;//如果名称不存在,则启动
c[k][type]=c[k][type]| |【】//如果宠物不存在,则启动
c[k][type].push(p);//添加宠物
返回c;
}, {}));
控制台日志(结果)
确定组的答案:

首先,我们创建具有所需对象结构的数组

    var newPeople = people.map(function(item){
    var newPeople = {};
    newPeople.name = item.name;
    newPeople.surname = item.surname;
    var type = item.pet.type; 
    newPeople[type] = [];
    var petDetails = {
        name: item.pet.name,
        age: item.pet.age
    } 
    newPeople[type].push(petDetails);
    return newPeople;
});

/*Output: people = [{name: "John", surname: "Doe", CAT: Array(1)},
                    {name: "John", surname: "Doe", DOG: Array(1)}, 
                    {name: "Jane", surname: "Doe", CAT: Array(1)},
                    {name: "Jane", surname: "Doe", CAT: Array(1)}]*/
现在,我们将使用以下循环对它们进行分组:

for (var i = 0; i < newPeople.length; i++) {
    for(var j = i+1; j < newPeople.length;j++){
        var item = newPeople[i];
        var nextItem = newPeople[j];
        if(item.name === nextItem.name && item.surname === nextItem.surname) {
            var firstItemKeys = Object.keys(item);
            var nextItemKeys = Object.keys(nextItem);
            if(firstItemKeys[2] === nextItemKeys[2]) {
                item[firstItemKeys[2]].push(nextItem[nextItemKeys[2]][0]);
            } else {
                if (Array.isArray(item[nextItemKeys[2]])) {
                    item[nextItemKeys[2]].push(nextItem[nextItemKeys[2]][0]);
                } else {
                    item[nextItemKeys[2]] = [];
                    item[nextItemKeys[2]].push(nextItem[nextItemKeys[2]][0]);
                }
            }
            newPeople.splice(j,1);
            j--
        }   
    }       
}

我将通过减少数组来实现这一点([参见array.prototype.reduce][1]

[1] :)

基本上,在遍历“人员”数据中的每个(当前)对象时创建聚合结果数组。检查是否存在具有person键的对象。如果有,则将新宠物添加到相应的宠物阵列中。否则,用当前宠物创建一个新的人

确保使用空数组初始化reduce函数(调用groupByPerson时的第二个参数)


如果您能够在整理API时使用库过渡,那么有一个函数可以为您处理这个问题。
    var newPeople = people.map(function(item){
    var newPeople = {};
    newPeople.name = item.name;
    newPeople.surname = item.surname;
    var type = item.pet.type; 
    newPeople[type] = [];
    var petDetails = {
        name: item.pet.name,
        age: item.pet.age
    } 
    newPeople[type].push(petDetails);
    return newPeople;
});

/*Output: people = [{name: "John", surname: "Doe", CAT: Array(1)},
                    {name: "John", surname: "Doe", DOG: Array(1)}, 
                    {name: "Jane", surname: "Doe", CAT: Array(1)},
                    {name: "Jane", surname: "Doe", CAT: Array(1)}]*/
for (var i = 0; i < newPeople.length; i++) {
    for(var j = i+1; j < newPeople.length;j++){
        var item = newPeople[i];
        var nextItem = newPeople[j];
        if(item.name === nextItem.name && item.surname === nextItem.surname) {
            var firstItemKeys = Object.keys(item);
            var nextItemKeys = Object.keys(nextItem);
            if(firstItemKeys[2] === nextItemKeys[2]) {
                item[firstItemKeys[2]].push(nextItem[nextItemKeys[2]][0]);
            } else {
                if (Array.isArray(item[nextItemKeys[2]])) {
                    item[nextItemKeys[2]].push(nextItem[nextItemKeys[2]][0]);
                } else {
                    item[nextItemKeys[2]] = [];
                    item[nextItemKeys[2]].push(nextItem[nextItemKeys[2]][0]);
                }
            }
            newPeople.splice(j,1);
            j--
        }   
    }       
}
newPeople = [{name: "John", surname: "Doe", CAT: Array(1), DOG: Array(1)},
{name: "Jane", surname: "Doe", CAT: Array(2)}]
let people = [{name: 'John',surname: 'Doe',pet: {type: 'CAT',name: 'whiskers',age: 1}},{name: 'John',surname: 'Doe',pet: {type: 'DOG', name: 'Dexter',age: 4}},{name: 'Jane',surname: 'Doe',pet: {type: 'CAT',name: 'Fluffy',age: 10}},{name: 'Jane',surname: 'Doe',pet: {type: 'CAT',name: 'Dennis',age: 3}}];
function groupByPerson(data) {
        return data.reduce( function (results, current) {
            const key = current.name + "_" + current.surname;
            let matched = results.filter(r => r.key === key)[0];
            if (matched) {
                let petArray = (current.pet.type === "CAT") ? matched.cats : matched.dogs;
                petArray.push({name:current.pet.name, age:current.pet.age});
            }
            else { 
                let newPerson = {
                    key: key,
                    name: current.name,
                    surname: current.surname,
                    cats: [],
                    dogs: []
                }
                let petArray = (current.pet.type === "CAT") ? newPerson.cats : newPerson.dogs;
                petArray.push({name:current.pet.name, age:current.pet.age});
                results.push(newPerson); 
            }    
            return results;
        }, []); // initialize with empty array
    }
    const results = groupByPerson(people);