计算数组中每个值有多少个对象

时间:2018-11-28 17:40:20

标签: javascript jquery arrays multidimensional-array

我有这个数组:

var markers = [
  {
    "type":"Chocolate",
    "name":"KitKat",
    "group":"candy",
    "icon":"candy",
    "coords":[5246,8980],
  },
  {
    "type":"Fruit",
    "name":"Orange",
    "group":"fruits",
    "icon":"fruis",
    "coords":[9012,5493],
  },
  {
    "type":"Fruit",
    "name":"Banana",
    "group":"fruits",
    "icon":"fruis",
    "coords":[9012,5493],
  },
  {
    "type":"Food",
    "name":"Rice",
    "group":"foods",
    "icon":"foods",
    "coords":[6724,9556],
  },
  {
    "type":"Food",
    "name":"Meat",
    "group":"foods",
    "icon":"foods",
    "coords":[6724,9556],
  },
  {
    "type":"Food",
    "name":"Beam",
    "group":"foods",
    "icon":"foods",
    "coords":[6724,9556],
  },
  {
    "type":"Liquid",
    "name":"Water",
    "group":"liquids",
    "icon":"liquids",
    "coords":[6724,9556],
  },
  {
    "type":"Liquid",
    "name":"Coffe",
    "group":"liquids",
    "icon":"liquids",
    "coords":[6724,9556],
  },
]

我想计算该数组中每个组有多少个项目。

我设法用这个来计数:

var count = []

for (var i = 0; i < markers.length; i++) {
  count[markers[i].group] = count[markers[i].group] + 1 || 1 ;
}

输出以下结果:

count = [
candy: 1
foods: 3
fruits: 2
liquids: 2
]

我想在另一部分中使用此值,为此,我需要将数组结构更改为类似以下内容:

count = [
{"item": "candy","qnt":1},
{"item": "foods","qnt":3},
{"item": "fruits","qnt":2},
{"item": "liquids","qnt":2}
]

我知道我可以做这样的事情:

var total_fruits = 0;
for (var i = 0; i < markers.length; i++) {
  if (markers[i].group == "fruits"){
    total_fruits++
  }
}

但是想像一下,如果一组超过50种类型的我需要多少个……

我将在html部分中使用与项目值类似的类相同的值:

<ul>
  <li class="candy">
    <span class="qnt">1</span>
  </li>
  <li class="fruits">
    <span class="qnt">2</span>
  </li>
  <li class="foods">
    <span class="qnt">3</span>
  </li>
  <li class="liquids">
    <span class="qnt">2</span>
  </li>
</ul>

有什么建议或如何改进?

9 个答案:

答案 0 :(得分:4)

您可以使用reduce()一步构建所需的对象。这将建立一个键为group的对象。要仅获取数组,请使用该对象的Object.values()

var markers = [{"type":"Chocolate","name":"KitKat","group":"candy","icon":"candy","coords":[5246,8980],},{"type":"Fruit","name":"Orange","group":"fruits","icon":"fruis","coords":[9012,5493],},{"type":"Fruit","name":"Banana","group":"fruits","icon":"fruis","coords":[9012,5493],},{"type":"Food","name":"Rice","group":"foods","icon":"foods","coords":[6724,9556],},{"type":"Food","name":"Meat","group":"foods","icon":"foods","coords":[6724,9556],},{"type":"Food","name":"Beam","group":"foods","icon":"foods","coords":[6724,9556],},{"type":"Liquid","name":"Water","group":"liquids","icon":"liquids","coords":[6724,9556],},{"type":"Liquid","name":"Coffe","group":"liquids","icon":"liquids","coords":[6724,9556],},]

let counts = markers.reduce((obj, {group}) => {
  if(!obj[group]) obj[group] = {"item": group, "qnt":1}  // make a count item if it doesn't exist
  else obj[group].qnt++                                  // or increment it
  return obj
}, {})

console.log(Object.values(counts))

答案 1 :(得分:2)

预期的输出不正确。数组不能具有这样的键和值。您可能需要一个对象。

var markers = [{
    "type": "Chocolate",
    "name": "KitKat",
    "group": "candy",
    "icon": "candy",
    "coords": [5246, 8980],
  },
  {
    "type": "Fruit",
    "name": "Orange",
    "group": "fruits",
    "icon": "fruis",
    "coords": [9012, 5493],
  },
  {
    "type": "Fruit",
    "name": "Banana",
    "group": "fruits",
    "icon": "fruis",
    "coords": [9012, 5493],
  },
  {
    "type": "Food",
    "name": "Rice",
    "group": "foods",
    "icon": "foods",
    "coords": [6724, 9556],
  },
  {
    "type": "Food",
    "name": "Meat",
    "group": "foods",
    "icon": "foods",
    "coords": [6724, 9556],
  },
  {
    "type": "Food",
    "name": "Beam",
    "group": "foods",
    "icon": "foods",
    "coords": [6724, 9556],
  },
  {
    "type": "Liquid",
    "name": "Water",
    "group": "liquids",
    "icon": "liquids",
    "coords": [6724, 9556],
  },
  {
    "type": "Liquid",
    "name": "Coffe",
    "group": "liquids",
    "icon": "liquids",
    "coords": [6724, 9556],
  },
]


let count = markers.reduce(function(acc, curr) {
  if (acc[curr.type]) {
    acc[curr.type] += 1;
  } else {
    acc[curr.type] = 1;
  }

  return acc;
}, {})

console.log(count)

/* if you need an array of objects then ,instead of object ,
pass an empty array as the accumulator. Then in that 
accumulator search if the type exist using findIndex.
If it returns -1 then create a new object with 
required values and push it in the accumulator,
 else update the value of qnt at that specific index*/

let count1 = markers.reduce(function(acc, curr) {
  let getItemIndex = acc.findIndex(function(item) {
    return item.item === curr.group
  });

  if (getItemIndex === -1) {
    let obj = {
      item: curr.group,
      qnt: 1
    }
    acc.push(obj)
  } else {
    acc[getItemIndex].qnt += 1;
  }

  return acc;
}, [])

console.log(count1)

答案 2 :(得分:2)

您可以通过Array.reduce执行此操作,以group进行分组,然后将Object.entriesArray.map一起使用以获取所需的输出格式:

var data = [ { "type":"Chocolate", "name":"KitKat", "group":"candy", "icon":"candy", "coords":[5246,8980], }, { "type":"Fruit", "name":"Orange", "group":"fruits", "icon":"fruis", "coords":[9012,5493], }, { "type":"Fruit", "name":"Banana", "group":"fruits", "icon":"fruis", "coords":[9012,5493], }, { "type":"Food", "name":"Rice", "group":"foods", "icon":"foods", "coords":[6724,9556], }, { "type":"Food", "name":"Meat", "group":"foods", "icon":"foods", "coords":[6724,9556], }, { "type":"Food", "name":"Beam", "group":"foods", "icon":"foods", "coords":[6724,9556], }, { "type":"Liquid", "name":"Water", "group":"liquids", "icon":"liquids", "coords":[6724,9556], }, { "type":"Liquid", "name":"Coffe", "group":"liquids", "icon":"liquids", "coords":[6724,9556], }, ]

const group = data.reduce((r,c) => (r[c.group] = (r[c.group] || 0) + 1, r), {})
console.log(Object.entries(group).map(([k,v]) => ({ item: k, qnt: v })))

答案 3 :(得分:2)

var markers = [{
    "type": "Chocolate",
    "name": "KitKat",
    "group": "candy",
    "icon": "candy",
    "coords": [5246, 8980],
  },
  {
    "type": "Fruit",
    "name": "Orange",
    "group": "fruits",
    "icon": "fruis",
    "coords": [9012, 5493],
  },
  {
    "type": "Fruit",
    "name": "Banana",
    "group": "fruits",
    "icon": "fruis",
    "coords": [9012, 5493],
  },
  {
    "type": "Food",
    "name": "Rice",
    "group": "foods",
    "icon": "foods",
    "coords": [6724, 9556],
  },
  {
    "type": "Food",
    "name": "Meat",
    "group": "foods",
    "icon": "foods",
    "coords": [6724, 9556],
  },
  {
    "type": "Food",
    "name": "Beam",
    "group": "foods",
    "icon": "foods",
    "coords": [6724, 9556],
  },
  {
    "type": "Liquid",
    "name": "Water",
    "group": "liquids",
    "icon": "liquids",
    "coords": [6724, 9556],
  },
  {
    "type": "Liquid",
    "name": "Coffe",
    "group": "liquids",
    "icon": "liquids",
    "coords": [6724, 9556],
  }
];

var temp = markers.reduce( function ( results, marker ) {
  results[ marker.group ] = ( results[ marker.group ] || 0 ) + 1;
  
  return results;
}, {});

//now convert the object to a list like you want it
temp = Object.keys( temp ).map( function ( group ) {
  return { group: group, quantity: temp[ group ] };
} );

console.log( temp );

答案 4 :(得分:2)

(我认为)最好的方法是使用{ item: count }这样的格式,除了count应该是对象{}而不是数组{{1 }}(请参阅@brk's answer)。如果您希望输出为对象数组,则只需使用一个缓存对象(该对象将保存[]数组中count对象的索引):

count

答案 5 :(得分:1)

您可以使用reduce方法返回包含项目和数量的新数组。

我们使用三元语句来确定累加器数组是否已经包含带有findIndex的组类型。如果没有,我们将qnt推为1的新类型,如果是,我们只需增加qnt值即可。

markers.reduce((ms, m) => (ms.findIndex(o => o.item === m["group"]) > 0) ? 
(ms[ms.findIndex(o => o.item === m["group"])]["qnt"]++, ms) : 
(ms.push({  qnt: 1,  item: m["group"]}), ms), []);

var markers=[{type:"Chocolate",name:"KitKat",group:"candy",icon:"candy",coords:[5246,8980]},{type:"Fruit",name:"Orange",group:"fruits",icon:"fruis",coords:[9012,5493]},{type:"Fruit",name:"Banana",group:"fruits",icon:"fruis",coords:[9012,5493]},{type:"Food",name:"Rice",group:"foods",icon:"foods",coords:[6724,9556]},{type:"Food",name:"Meat",group:"foods",icon:"foods",coords:[6724,9556]},{type:"Food",name:"Beam",group:"foods",icon:"foods",coords:[6724,9556]},{type:"Liquid",name:"Water",group:"liquids",icon:"liquids",coords:[6724,9556]},{type:"Liquid",name:"Coffe",group:"liquids",icon:"liquids",coords:[6724,9556]}];

let r = markers.reduce((ms, m) => (ms.findIndex(o => o.item === m["group"]) > 0) ? 
(ms[ms.findIndex(o => o.item === m["group"])]["qnt"]++, ms) : 
(ms.push({  qnt: 1,  item: m["group"]}), ms), []);

console.log(r);

答案 6 :(得分:1)

count = {
  candy: 1
  foods: 3
  fruits: 2
  liquids: 2
}

从初始数据计算出分组计数后,您可以将其发送以查看以生成html。 (这是一个对象,而不是数组)。 生成html时,您可以像这样遍历其属性:

//Add ul
for(var item in count) {
   //Get data and add li (item = candy, count[item] = 1)
}

答案 7 :(得分:1)

您可以使用您的代码

var count = {} // I made an Object out of your Array, the proper way to do this

for (var i = 0; i < markers.length; i++) {
  count[markers[i].group] = count[markers[i].group] + 1 || 1 ;
}

然后将您的对象转换为数组:

var finalArray = [];
for(var key in count)
  finalArray.push({item: key, qnt: count[key]});
}

答案 8 :(得分:1)

var markers = [{"type":"Chocolate","name":"KitKat","group":"candy","icon":"candy","coords":[5246,8980]},{"type":"Fruit","name":"Orange","group":"fruits","icon":"fruis","coords":[9012,5493]},{"type":"Fruit","name":"Banana","group":"fruits","icon":"fruis","coords":[9012,5493]},{"type":"Food","name":"Rice","group":"foods","icon":"foods","coords":[6724,9556]},{"type":"Food","name":"Meat","group":"foods","icon":"foods","coords":[6724,9556]},{"type":"Food","name":"Beam","group":"foods","icon":"foods","coords":[6724,9556]},{"type":"Liquid","name":"Water","group":"liquids","icon":"liquids","coords":[6724,9556]},{"type":"Liquid","name":"Coffe","group":"liquids","icon":"liquids","coords":[6724,9556]}]

counts = []
markers.map(marker => counts.filter(type => type.name == marker.group).length> 0 ? counts.filter(type=>type.name ==marker.group)[0].count ++ : counts.push({'name':marker.group,'count':1}));
console.log(counts);

这或如上文所述,使用reduce也可以。 由于有多个地图和过滤器,因此效率也很低