我该如何通过一个对象属性计算一个对象数组中唯一元素的数量?

3

我有一个orders数组。

orders = [
  {table_id: 3, food_id: 5},
  {table_id: 4, food_id: 2},
  {table_id: 1, food_id: 6},
  {table_id: 3, food_id: 4},
  {table_id: 4, food_id: 6},
];

我想写一个函数来计算数组中唯一的table_id或food_id的数量。例如,
唯一的table_id列表是1,3,4,总数为3。 唯一的food_id列表是2,4,5,6,总数为4。
我该如何实现?

1
表格 ID 为 4 是怎么回事?为什么你不计算它?另外,你确切地尝试了什么? - Philipp Sander
2
一种方法:new Set(orders.map(x => x.table_id)).size - Felix Kling
哇!这是最棒的一行代码!谢谢@FelixKling - anonym
@anonym,我在我的答案中加入了Felix Kings的代码行并解释了它的工作原理。 - Cruiser
10个回答

4

可能会有类似这样的解决方案:

function countTableId(orders){
    // sets are, well, sets of unique items. no duplicates allowed
    let uniqueId = new Set();
    for(let ord of orders){
        uniqueId.add(ord.table_id);
    }
    // the size of the set is the number of unique items we added
    return uniqueId.size;
}

你可以在另一个函数中使用food_id属性来完成同样的操作。
@Felix King有一种一行代码的方法,非常棒。它使用了set对象和Array.prototype.map()。
let unique_table_id_count = new Set(orders.map(x => x.table_id)).size
let unique_food_id_count = new Set(orders.map(x => x.food_id)).size

.map() 方法将循环遍历数组并查看每个 table_id,然后尝试将其添加到集合中。如果集合已经存在该元素,则集合对象将丢弃该元素,因此我们只获得唯一值。最后,由于链接作用,我们只需获取集合的大小即可完成!


1
值得注意的是,您无需检查集合是否已经具有该ID,因为如果将重复的值添加到集合中,集合不会保留它们。所以这就是为什么@Felix Klings的解决方案可行的原因。 - Saad

3

我相信你还没有尝试过,因为它和看起来一样简单:

1 - 初始化数组

var unique_table_ids = [];
var unique_food_ids = [];

2 - 循环遍历订单并填充数组

for (var i = 0; i < orders.length; i++) {
    if (unique_table_ids.indexOf(orders[i].table_id) == -1) // if this Table ID wasn't already in the unique table ID list
        unique_table_ids.push(orders[i].table_id);          // Add the table ID to the unique table ID list
    if (unique_food_ids.indexOf(orders[i].table_id) == -1)  // if this Food ID wasn't already in the unique food ID list
        unique_food_ids.push(orders[i].food_id);            // Add the food ID to the unique food ID list
}

现在,根据你当前的order数组,unique_table_idsunique_food_ids的相应值为:
unique_table_ids // = [3, 4, 1];
unique_food_ids // = [5, 2, 6, 4];

当然,您可以获取它们的长度:
unique_table_ids.length // = 3
unique_food_ids.length // = 4

我怎么没想到呢?非常感谢。 - anonym

2

简单地说:

var results = {};

orders.forEach(function(item) {
  for (var key in item) {
    results[key] = results[key] || [];
    if (results[key].indexOf(item[key]) == -1)
      results[key].push(item[key]);
  }
})

for (var key in results) {
  console.log("The list of unique "+ key +" are "+ results[key] +" which totals "+ results[key].length);
}

这段内容涉及IT技术,不需要新的数据结构,只需使用结果对象,无需编辑现有代码,而且最重要的是不需要预先知道订单对象的键。


1
将这些值添加到 Set 中并获取其大小。
如果您需要 es5 解决方案,则可以自己实现一个集合类。

1
你可以创建一个不同的表格和食品ID列表,并同时对它们进行计数。这段代码将创建两个包含信息的对象...

var orders = [
  {table_id: 3, food_id: 5},
  {table_id: 4, food_id: 2},
  {table_id: 1, food_id: 6},
  {table_id: 3, food_id: 4},
  {table_id: 4, food_id: 6},
];

var tables = {};
var foods = {};

for (var i in orders) {
  var order = orders[i];
  var tableId = "table_id_" + order.table_id;
  var foodId = "food_id_" + order.food_id;

 if (tables.hasOwnProperty(tableId)) {
   tables[tableId]++;
  }
  else {
   tables[tableId] = 1;
  }
  
  if (foods.hasOwnProperty(foodId)) {
   foods[foodId]++;
  }
  else {
   foods[foodId] = 1;
  }
}

console.log(tables);
console.log(foods);

对于其他感到不适的人,我为使用变量“foods”道歉。这是我的习惯。


1

完成了!

orders = [
  {table_id: 3, food_id: 5},
  {table_id: 4, food_id: 2},
  {table_id: 1, food_id: 6},
  {table_id: 3, food_id: 4},
  {table_id: 4, food_id: 6},
];

var result=[];
var result2=[];

for(var i=0; i<orders.length; i++){
  var current=orders[i];
  var ti = current.table_id;
  var push=true;
  for(var j=0; j<result.length;j++){
    if(ti==result[j]){
      push = false;
    }
  }
  if(push){result.push(ti);}
  
  var fi = current.food_id;
  push=true;
  for(var j=0; j<result2.length;j++){
    if(fi==result2[j]){
      push = false;
    }
  }
  if(push){result2.push(fi);}
}
console.log(result + " " + result2);
console.log("Unique Tables: " + result.length + " Unique Foods: " + result2.length);


1

你可以结合使用 Array.prototype.sortArray.prototype.filter

type Order = {
    table_id: number;
    food_id: number;
}

let orders = [
  {table_id: 3, food_id: 5},
  {table_id: 4, food_id: 2},
  {table_id: 1, food_id: 6},
  {table_id: 3, food_id: 4},
  {table_id: 4, food_id: 6},
] as Order[];

let uniques = orders.sort((a, b) => a.table_id - b.table_id)
    .filter((value, index, array) => index === array.length - 1 || array[index + 1].table_id !== value.table_id);

console.log(uniques.length); // 3

(在playground中的代码)


0
你可以使用 Set 和映射所需的部分。

var orders = [{ table_id: 3, food_id: 5 }, { table_id: 4, food_id: 2 }, { table_id: 1, food_id: 6 }, { table_id: 3, food_id: 4 }, { table_id: 4, food_id: 6 }], 
    getUnique = key => [...new Set(orders.map(o => o[key]))];
  
console.log(getUnique('table_id'));
console.log(getUnique('food_id'));
.as-console-wrapper { max-height: 100% !important; top: 0; }


0

var orders = [
  {table_id: 3, food_id: 5},
  {table_id: 4, food_id: 2},
  {table_id: 1, food_id: 6},
  {table_id: 3, food_id: 4},
  {table_id: 4, food_id: 6},
  {table_id: 4, food_id: 6},
  {table_id: 4, food_id: 6}
];
  
var tableObj = {}, foodObj = {};
orders.forEach(function(e){
  tableObj[e.table_id] = null;
  foodObj[e.food_id] = null;
});

var tableUniqueIDs =  Object.keys(tableObj);
var foodUniqueIDs = Object.keys(foodObj);

console.log("table IDs: ", tableUniqueIDs);
console.log("food IDs: ", foodUniqueIDs);


0

orders = [
  {table_id: 3, food_id: 5},
  {table_id: 4, food_id: 2},
  {table_id: 1, food_id: 6},
  {table_id: 3, food_id: 4},
  {table_id: 4, food_id: 6},
];
  
function count(arr, key) {
    res = []; 
    arr.map(obj => obj[key])
        .filter(n => res.indexOf(n) <= -1 && res.push(n))

    return res.length;
}

console.log(count(orders, 'table_id'));
console.log(count(orders, 'food_id'));

PS:虽然使用&&有点hackish...


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