0

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 ?

4
  • 1
    definitely not the most efficient. consider that final[i].join(';') always returns the same thing, but it's being run six (6) times per element in your array. Commented Oct 21, 2020 at 13:18
  • Consider using reduce developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Commented Oct 21, 2020 at 13:19
  • Well the code is very inefficient in the fact you are joining on every check. Commented Oct 21, 2020 at 13:19
  • it looks like the arrays have positional data. ie, part number always appears in the first position, and maker Nissan or Toyota always appears in the second position, etc. You probably don't need to use .join at all Commented Oct 21, 2020 at 13:20

6 Answers 6

3
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);

Sign up to request clarification or add additional context in comments.

Comments

3

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)

Comments

2

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);

Comments

2

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,
});

Comments

2

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);

Comments

2

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.