简体   繁体   中英

Javascript count number of occurrence

I have the following array data and i am calculating the number of records that match using the includes criteria.

var final = 
[
  [
    "61131",
    "NISSAN",
    "BOLTON",
    "MAINT"
  ],
  [
    "61132",
    "NISSAN",
    "BOLTON",
    "MAINT"
  ],
  [
    "61133",
    "TOYOTA",
    "STOCKPORT",
    "STORED"
  ],
  [
    "61134",
    "TOYOTA",
    "STOCKPORT",
    "MAINT"
  ],
  [
    "61135",
    "NISSAN",
    "STOCKPORT",
    "MAINT"
  ],
  [
    "61136",
    "NISSAN",
    null,
    null
  ]
]

and the code is this one :

var obj = {};
var num1 = 0;
var num2 = 0;
for (var i=0; i<final.length; i++){
    if(final[i].join(';').includes('BOLTON') && final[i].join(';').includes('MAINT') && final[i].join(';').includes('NISSAN')) {
        num1++;
    }
}

for (var i=0; i<final.length; i++){
    if(final[i].join(';').includes('STOCKPORT') && final[i].join(';').includes('STORED') && final[i].join(';').includes('TOYOTA')) {
        num2++;
    }
}


obj['BOLTON_MAINT_NISSAN'] = num1
obj['STOCKPORT_STORED_TOYOTA'] = num2

console.log(obj)

output

  {  "BOLTON_MAINT_NISSAN": 2, "STOCKPORT_STORED_TOYOTA": 1}

I am getting the desired result, is there a more efficient way of writing the above code that is minimal ?

const count = (list, keys) => {
  return keys.reduce(
    (obj, key) => ({
      ...obj,
      [key]: list.filter(sublist =>
        key.split('_').every(keyPart => sublist.includes(keyPart))
      ).length
    }),
    {}
  );
};

count(final, ['BOLTON_MAINT_NISSAN', 'STOCKPORT_STORED_TOYOTA'])

 const final = [ [ "61131", "NISSAN", "BOLTON", "MAINT" ], [ "61132", "NISSAN", "BOLTON", "MAINT" ], [ "61133", "TOYOTA", "STOCKPORT", "STORED" ], [ "61134", "TOYOTA", "STOCKPORT", "MAINT" ], [ "61135", "NISSAN", "STOCKPORT", "MAINT" ], [ "61136", "NISSAN", null, null ] ]; const count = (list, keys) => { return keys.reduce( (obj, key) => ({ ...obj, [key]: list.filter(sublist => key.split('_').every(keyPart => sublist.includes(keyPart)) ).length }), {} ); }; var bmtNsst = count(final, ['BOLTON_MAINT_NISSAN', 'STOCKPORT_STORED_TOYOTA']); console.log(bmtNsst);

Using reduce, slice to get rid of the number, filter to get rid of the nulls, and join to make it the key.

 var final = [ ["61131", "NISSAN", "BOLTON", "MAINT"], ["61132", "NISSAN", "BOLTON", "MAINT"], ["61133", "TOYOTA", "STOCKPORT", "STORED"], ["61134", "TOYOTA", "STOCKPORT", "MAINT"], ["61135", "NISSAN", "STOCKPORT", "MAINT"], ["61136", "NISSAN", null, null] ]; var grouped = final.reduce(function(obj, data) { var key = data.slice(1).filter(Boolean).join("_"); obj[key] = (obj[key] || 0) + 1; return obj; }, {}); console.log(grouped)

There is no need to use String.join . Array has also got function Array.prototype.includes to check if item is existed in array or not.

Using that, you can find the subArray that satisfies your condition. And using Array.prototype.filter , you can extract the sub-arrays to satisfy the conditions as follows.

 const final = [ [ "61131", "NISSAN", "BOLTON", "MAINT" ], [ "61132", "NISSAN", "BOLTON", "MAINT" ], [ "61133", "TOYOTA", "STOCKPORT", "STORED" ], [ "61134", "TOYOTA", "STOCKPORT", "MAINT" ], [ "61135", "NISSAN", "STOCKPORT", "MAINT" ], [ "61136", "NISSAN", null, null ] ]; const num1Arr = final.filter((item) => item.includes('BOLTON') && item.includes('MAINT') && item.includes('NISSAN')); const num2Arr = final.filter((item) => item.includes('STOCKPORT') && item.includes('STORED') && item.includes('TOYOTA')); const output = { BOLTON_MAINT_NISSAN: num1Arr.length, STOCKPORT_STORED_TOYOTA: num2Arr.length }; console.log(output);

Or simply, you can do it using Array.prototype.reduce .

 const final = [ [ "61131", "NISSAN", "BOLTON", "MAINT" ], [ "61132", "NISSAN", "BOLTON", "MAINT" ], [ "61133", "TOYOTA", "STOCKPORT", "STORED" ], [ "61134", "TOYOTA", "STOCKPORT", "MAINT" ], [ "61135", "NISSAN", "STOCKPORT", "MAINT" ], [ "61136", "NISSAN", null, null ] ]; const output = final.reduce((acc, cur) => { if (cur.includes('BOLTON') && cur.includes('MAINT') && cur.includes('NISSAN')) { acc['BOLTON_MAINT_NISSAN'] ++; } if (cur.includes('STOCKPORT') && cur.includes('STORED') && cur.includes('TOYOTA')) { acc['STOCKPORT_STORED_TOYOTA'] ++; } return acc; }, { BOLTON_MAINT_NISSAN: 0, STOCKPORT_STORED_TOYOTA: 0 }); console.log(output);

 const final = [ [ "61131", "NISSAN", "BOLTON", "MAINT" ], [ "61132", "NISSAN", "BOLTON", "MAINT" ], [ "61133", "TOYOTA", "STOCKPORT", "STORED" ], [ "61134", "TOYOTA", "STOCKPORT", "MAINT" ], [ "61135", "NISSAN", "STOCKPORT", "MAINT" ], [ "61136", "NISSAN", null, null ] ]; console.log({ BOLTON_MAINT_NISSAN: final.filter((value) => { return value[1] === 'NISSAN' && value[2] === 'BOLTON' && value[3] === 'MAINT'; }).length, STOCKPORT_STORED_TOYOTA: final.filter((value) => { return value[1] === 'TOYOTA' && value[2] === 'STOCKPORT' && value[3] === 'STORED'; }).length, });

Using Array.prototype.reduce() :

 const final = [ [ "61131", "NISSAN", "BOLTON", "MAINT" ], [ "61132", "NISSAN", "BOLTON", "MAINT" ], [ "61133", "TOYOTA", "STOCKPORT", "STORED" ], [ "61134", "TOYOTA", "STOCKPORT", "MAINT" ], [ "61135", "NISSAN", "STOCKPORT", "MAINT" ], [ "61136", "NISSAN", null, null ] ]; let occurrence = final.reduce((obj, item)=>{ var key=item[2]+"_"+item[3]+"_"+item[1]; if(!obj[key]) obj[key]=0; obj[key]++; return obj; },{}); console.log(occurrence);

In your solution, you iterate twice through the array, which is unnecessary as if an object is one of the two you're searching, then it is not the other, so you can do all in one loop.

 var final = [ ["61131", "NISSAN", "BOLTON", "MAINT"], ["61132", "NISSAN", "BOLTON", "MAINT"], ["61133", "TOYOTA", "STOCKPORT", "STORED"], ["61134", "TOYOTA", "STOCKPORT", "MAINT"], ["61135", "NISSAN", "STOCKPORT", "MAINT"], ["61136", "NISSAN", null, null] ]; var obj = { BOLTON_MAINT_NISSAN: 0, STOCKPORT_STORED_TOYOTA: 0 }; final.forEach(y => { let x = y.join(';'); if(x.includes('BOLTON') && x.includes('MAINT') && x.includes('NISSAN')) obj.BOLTON_MAINT_NISSAN++; else if ( x.includes('STOCKPORT') && x.includes('STORED') && x.includes('TOYOTA') ) obj.STOCKPORT_STORED_TOYOTA++; }) console.log(obj)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM