如何将数组元素添加到另一个对象中并计算数量

3
首先,我有一个包含对象元素的数组,如下所示:
$scope.selectedIngredient = [object1, object2, object3, object1, object2];

其次,我有一个新对象:
$scope.selectedIngredientResults = {};

现在我想要用JavaScript实现以下功能:

计算数组中每个对象元素的数量,并将其放入一个新对象中并存储每个计数。

$scope.selectedIngredientResults = [

    {"object" : object1, "count" : 2},
    {"object" : object2, "count" : 2},
    {"object" : object3, "count" : 1}

];

这里是一个包含对象元素的数组

[![这里是新的对象结果,这就是我想要的,

我尝试使用

$scope.addIngredient = function(selectedElement) {

console.log('selectedElement', selectedElement);
$scope.selectedIngredient.push(selectedElement);
console.log('$scope.selectedIngredient' , $scope.selectedIngredient);
$scope.selectedIngredientResults = {};
var lengthofR = $scope.selectedIngredient.length;

for (var i = lengthofR - 1; i >= 0; i--) {
    var selected = $scope.selectedIngredient[i]['ingredient_id'];
    console.log('lengthofR', lengthofR);
    if(selected){
        if($scope.selectedIngredientResults.hasOwnProperty(selected)){

            $scope.selectedIngredientResults[$scope.selectedIngredient]++;
        }else {
      $scope.selectedIngredientResults[$scope.selectedIngredient] = 1;
        }
         console.log('$scope.selectedIngredientResults', $scope.selectedIngredientResults ); 
        }
    }

}

你是如何确定两个对象是否相同的(它们实际上是相同的对象还是只有相同的属性)? - Paddy
请添加一些用于计数的数据。 - Nina Scholz
@ Paddy 每个对象都有 ingredient_id,使用 obj.hasOwnProperty 来识别。for (var i = lengthofR - 1; i >= 0; i--) { var selected = $scope.selectedIngredient[i]['ingredient_id']; console.log('lengthofR', lengthofR); if(selected){ if($scope.selectedIngredientResults.hasOwnProperty(selected)){ $scope.selectedIngredientResults[$scope.selectedIngredient]++; }else { $scope.selectedIngredientResults[$scope.selectedIngredient] = 1; } - Agnes
我知道这不是答案,但对于这种任务来说,lodash非常棒 https://lodash.com/ - Daniel Apt
如果这是一个AngularJS的问题,请标记为这样,因为它可能会添加不同的考虑,而不是使用原始的Javascript。 - Boaz
4个回答

1
首先,您需要按照您的键应用group by。然后从分组中提取结果。这是一个转换函数,您需要使用它。
function transform(items) {
    items = items.reduce(function (memo, val) {
        var key = val['ingredient_id'];
        if (!memo[key]) {
            memo[key] = [];
        }
        memo[key].push(val);

        return memo;
    }, {});

    var result = [];
    for (var k in items) {
        var groups = items[k];
        result.push({ 'object': groups[0], 'count': groups.length });
    }

    return result;
}

我正在努力理解你的代码,但是我仍然无法理解这里发生了什么。items = items.reduce(function (memo, val) { var key = val['ingredient_id']; if (!memo[key]) { memo[key] = []; } memo[key].push(val); return memo; }, {}); - Agnes
它正在应用group by操作。当减少操作完成时,只需console.log(items),您就会知道已完成的操作。要了解有关reduce的更多信息,请参见(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce)。:) - Sufian Saory
能否解释一下 val['ingredient_id']?@Sufian Saory - Agnes
1
val是当前用于缩减迭代的对象。val ['ingredient_id']是ingredient_id的值,它是我们分组操作的键。请参见(http://www.w3schools.com/jsref/jsref_reduce.asp),其中包含reduce的示例。 - Sufian Saory
感谢 @Sufian Saory - Agnes

0
function getIngredientResults (ingredients) {
  var source = [].slice.call(ingredients)
  var result = []

  while (source.length > 0) {
    // Move first item from source.
    var current = source.shift()

    // Find indexes of duplicate entries.
    var duplicateIndexes = source.reduce(function (carry, item, index) {
      if (item.ingredient_id === current.ingredient_id) {
        carry.push(index)
      }

      return carry
    }, [])

    // Remove duplicates from source.
    duplicateIndexes.forEach(function (index) {
      source.splice(index, 1)
    })

    // Add data to result
    result.push({
      ingredient: current,
      count: duplicateIndexes.length + 1
    })
  }

  return result
}

抱歉 @Jon Koops,这是我的错,我应该标记为AngularJS,但还是感谢您的帮助。 - Agnes
这只是一个函数,你可以在AngularJS中使用它。AngularJS仍然是JavaScript... - Jon Koops

0

我猜这个问题已经有人回答过了,但是下面是如何用一次reduce来实现:

$scope.selectedIngredientResults = $scope.selectedIngredient.reduce(function (result, item) {
    var foundIndex = -1;
    var found = result.some(function (alreadyCounted, i) {
        if (alreadyCounted.object.ingredient_id === item.ingredient_id) {
            foundIndex = i;
            return true;
        }
        return false;
    });
    if (found && foundIndex !== -1) result[foundIndex].count += 1;
    else result.push({object: item, count: 1});
    return result;
}, []);

0
我花了一些时间学习了你们的答案上介绍的新方法,并从中获得了一些灵感,最终用另外一种方式解决了问题。非常感谢你们!
myApp.controller('addIngredientCtrl', function($scope) {
$scope.selectedIngredient = [];

$scope.addIngredient = function(selectedElement) {
var elementIndex = $scope.selectedIngredient.indexOf(selectedElement);
if(elementIndex === -1) {
  selectedElement['customerCartQuantity'] = 1;
  $scope.selectedIngredient.push(selectedElement);
} else {
  $scope.changeIngredientQuantity($scope.selectedIngredient[elementIndex],   1);
 }
 }

$scope.changeIngredientQuantity = function(selectedElement, value) {
var elementIndex = $scope.selectedIngredient.indexOf(selectedElement);
$scope.selectedIngredient[elementIndex].customerCartQuantity += value; 
if($scope.selectedIngredient[elementIndex].customerCartQuantity == 0) {
  $scope.selectedIngredient.splice(elementIndex, 1);
}

} });


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接