对数组中的值进行分组和计数

时间:2021-12-09 21:36:55

I have an array with objects, like the following.

我有一个包含对象的数组,如下所示。

b = {
  "issues": [{
    "fields": {
      "status": {
        "id": "200",
        "name": "Backlog"
      }
    }
  }, {
    "fields": {
      "status": {
        "id": "202",
        "name": "close"
      }
    }
  }, {
    "fields": {
      "status": {
        "id": "201",
        "name": "close"
      }
    }
  }]
};

I want to count how many issues have status close, and how many have backlog. I'd like to save the count in a new array as follows.

我想计算有多少问题的状态接近,有多少有积压。我想将计数保存在一个新数组中,如下所示。

a = [
  {Name: 'Backlog', count: 1},
  {Name: 'close', count: 2}
];

I have tried the following.

我尝试了以下内容。

b.issues.forEach(function(i) {
  var statusName = i.fields.status.name;

  if (statusName in a.Name) {
    a.count = +1;
  } else {
    a.push({
      Name: statusName,
      count: 1
    });
  }
});

That however doesn't seem to be working. How should I implement this?

然而,这似乎不起作用。我该如何实现呢?

4 个解决方案

#1


12  

This is a perfect opportunity to use Array#reduce. That function will take a function that is applied to all elements of the array in order and can be used to accumulate a value. We can use it to accumulate an object with the various counts in it.

这是使用Array#reduce的绝佳机会。该函数将采用一个按顺序应用于数组的所有元素的函数,并可用于累积值。我们可以使用它来累积具有各种计数的对象。

To make things easy, we track the counts in an object as simply {name: count, otherName: otherCount}. For every element, we check if we already have an entry for name. If not, create one with count 0. Otherwise, increment the count. After the reduce, we can map the array of keys, stored as keys of the object, to be in the format described in the question. See below.

为了简单起见,我们只是简单地跟踪对象中的计数{name:count,otherName:otherCount}。对于每个元素,我们检查是否已有名称条目。如果不是,请创建一个计数为0.否则,递增计数。在reduce之后,我们可以将存储为对象的键的键数组映射到问题中描述的格式。见下文。

var b = {
  "issues": [{
    "fields": {
      "status": {
        "id": "200",
        "name": "Backlog"
      }
    }
  }, {
    "fields": {
      "status": {
        "id": "202",
        "name": "close"
      }
    }
  }, {
    "fields": {
      "status": {
        "id": "201",
        "name": "close"
      }
    }
  }]
};

var counts = b.issues.reduce((p, c) => {
  var name = c.fields.status.name;
  if (!p.hasOwnProperty(name)) {
    p[name] = 0;
  }
  p[name]++;
  return p;
}, {});

console.log(counts);

var countsExtended = Object.keys(counts).map(k => {
  return {name: k, count: counts[k]}; });

console.log(countsExtended);
.as-console-wrapper {
  max-height: 100% !important;
}

Notes.

笔记。

  1. Array#reduce does not modify the original array.
  2. Array#reduce不会修改原始数组。
  3. You can easily modify the function passed to reduce to for example not distinguish between Backlog and backlog by changing

    您可以轻松修改传递给reduce的函数,例如通过更改来区分Backlog和backlog

    var name = c.fields.status.name;
    

    into

    var name = c.fields.status.name.toLowerCase();
    

    for example. More advanced functionality can also easily be implemented.

    例如。还可以轻松实现更高级的功能。

#2


1  

Using ES6 Arrow functions you can do it with minimum syntax

使用ES6 Arrow功能,您可以使用最少的语法执行此操作

var b = {
    "issues": [{
        "fields": {
            "status": {
                "id": "200",
                "name": "Backlog"
            }
        }
    }, {
        "fields": {
            "status": {
                "id": "202",
                "name": "close"
            }
        }
    }, {
        "fields": {
            "status": {
                "id": "201",
                "name": "close"
            }
        }
    }]
};

var countOfBackLog = b.issues.filter(x => {
return x.fields.status.name === "Backlog"
}).length

var countOfClose = b.issues.filter(x => {
return x.fields.status.name === "close"
}).length

a =[{Name: 'Backlog', count : countOfBackLog}, {Name: 'close', count : countOfClose}]

More about arrow functions here

更多关于箭头功能的信息

#3


0  

You can write like this. It is dynamic.

你可以这样写。这是动态的。

var a = {}; 
for(var key in b["issues"]){ 
    if(!a.hasOwnProperty(b["issues"][key].fields.status.name)){
     a[b["issues"][key].fields.status.name] = 1;
    }else{
     a[b["issues"][key].fields.status.name] = a[b["issues"][key].fields.status.name]+1;
    }
}
var c = [];
for(var key1 in a){
   c.push({
   name  : key1,
   count : a[key1]
   });
}

#4


0  

Something like this should do the trick. Simply iterate over your data, keep 2 counters with the number of each type of issue, and create the data format you want in the end. Try it live on jsfiddle.

这样的事情应该可以解决问题。只需迭代您的数据,保留2个计数器,每个类型的问题数量,并最终创建您想要的数据格式。在jsfiddle上试一试。

var b = {
    "issues": [{
        "fields": {
            "status": {
                "id": "200",
                "name": "Backlog"
            }
        }
    }, {
        "fields": {
            "status": {
                "id": "202",
                "name": "close"
            }
        }
    }, {
        "fields": {
            "status": {
                "id": "201",
                "name": "close"
            }
        }
    }]
};

var data = [];
for(var issue of b.issues){
    var entryFound = false;
    var tempObj = {
        name: issue.fields.status.name,
        count: 1
    };

    for(var item of data){
        if(item.name === tempObj.name){
        item.count++;
        entryFound = true;
        break;
      }
    }

    if(!entryFound){
        data.push(tempObj);
    }
}
console.log(data);

#1


12  

This is a perfect opportunity to use Array#reduce. That function will take a function that is applied to all elements of the array in order and can be used to accumulate a value. We can use it to accumulate an object with the various counts in it.

这是使用Array#reduce的绝佳机会。该函数将采用一个按顺序应用于数组的所有元素的函数,并可用于累积值。我们可以使用它来累积具有各种计数的对象。

To make things easy, we track the counts in an object as simply {name: count, otherName: otherCount}. For every element, we check if we already have an entry for name. If not, create one with count 0. Otherwise, increment the count. After the reduce, we can map the array of keys, stored as keys of the object, to be in the format described in the question. See below.

为了简单起见,我们只是简单地跟踪对象中的计数{name:count,otherName:otherCount}。对于每个元素,我们检查是否已有名称条目。如果不是,请创建一个计数为0.否则,递增计数。在reduce之后,我们可以将存储为对象的键的键数组映射到问题中描述的格式。见下文。

var b = {
  "issues": [{
    "fields": {
      "status": {
        "id": "200",
        "name": "Backlog"
      }
    }
  }, {
    "fields": {
      "status": {
        "id": "202",
        "name": "close"
      }
    }
  }, {
    "fields": {
      "status": {
        "id": "201",
        "name": "close"
      }
    }
  }]
};

var counts = b.issues.reduce((p, c) => {
  var name = c.fields.status.name;
  if (!p.hasOwnProperty(name)) {
    p[name] = 0;
  }
  p[name]++;
  return p;
}, {});

console.log(counts);

var countsExtended = Object.keys(counts).map(k => {
  return {name: k, count: counts[k]}; });

console.log(countsExtended);
.as-console-wrapper {
  max-height: 100% !important;
}

Notes.

笔记。

  1. Array#reduce does not modify the original array.
  2. Array#reduce不会修改原始数组。
  3. You can easily modify the function passed to reduce to for example not distinguish between Backlog and backlog by changing

    您可以轻松修改传递给reduce的函数,例如通过更改来区分Backlog和backlog

    var name = c.fields.status.name;
    

    into

    var name = c.fields.status.name.toLowerCase();
    

    for example. More advanced functionality can also easily be implemented.

    例如。还可以轻松实现更高级的功能。

#2


1  

Using ES6 Arrow functions you can do it with minimum syntax

使用ES6 Arrow功能,您可以使用最少的语法执行此操作

var b = {
    "issues": [{
        "fields": {
            "status": {
                "id": "200",
                "name": "Backlog"
            }
        }
    }, {
        "fields": {
            "status": {
                "id": "202",
                "name": "close"
            }
        }
    }, {
        "fields": {
            "status": {
                "id": "201",
                "name": "close"
            }
        }
    }]
};

var countOfBackLog = b.issues.filter(x => {
return x.fields.status.name === "Backlog"
}).length

var countOfClose = b.issues.filter(x => {
return x.fields.status.name === "close"
}).length

a =[{Name: 'Backlog', count : countOfBackLog}, {Name: 'close', count : countOfClose}]

More about arrow functions here

更多关于箭头功能的信息

#3


0  

You can write like this. It is dynamic.

你可以这样写。这是动态的。

var a = {}; 
for(var key in b["issues"]){ 
    if(!a.hasOwnProperty(b["issues"][key].fields.status.name)){
     a[b["issues"][key].fields.status.name] = 1;
    }else{
     a[b["issues"][key].fields.status.name] = a[b["issues"][key].fields.status.name]+1;
    }
}
var c = [];
for(var key1 in a){
   c.push({
   name  : key1,
   count : a[key1]
   });
}

#4


0  

Something like this should do the trick. Simply iterate over your data, keep 2 counters with the number of each type of issue, and create the data format you want in the end. Try it live on jsfiddle.

这样的事情应该可以解决问题。只需迭代您的数据,保留2个计数器,每个类型的问题数量,并最终创建您想要的数据格式。在jsfiddle上试一试。

var b = {
    "issues": [{
        "fields": {
            "status": {
                "id": "200",
                "name": "Backlog"
            }
        }
    }, {
        "fields": {
            "status": {
                "id": "202",
                "name": "close"
            }
        }
    }, {
        "fields": {
            "status": {
                "id": "201",
                "name": "close"
            }
        }
    }]
};

var data = [];
for(var issue of b.issues){
    var entryFound = false;
    var tempObj = {
        name: issue.fields.status.name,
        count: 1
    };

    for(var item of data){
        if(item.name === tempObj.name){
        item.count++;
        entryFound = true;
        break;
      }
    }

    if(!entryFound){
        data.push(tempObj);
    }
}
console.log(data);