Rishav Sinha
Rishav Sinha

Reputation: 359

calucate number of times a string appears in a array and compare with another array

i am stuck in getting no of times a string appears in array. This is my array

let arr = [ "5281-A", "5280-A", "5280-B", "5281-B" ]

used the split("-")[0] to get only the alpabets

now i would like a end result as this(getting Alphabets from every Element)

newObj = [['A',2], ['B',2]]

now this doesn't need to be array it can be object.But i want this in this form cause then i would like to compare the newObj with the following array

resArray = [["A",2], ["B",1]]

and then return in this case that B has one less quantity.

Basically it is a will used for validation of two different tabs values before submission.

I am stuck with this for hours. Help will be hugely appreciated.

Upvotes: 2

Views: 54

Answers (5)

Lioness100
Lioness100

Reputation: 8412

You can use Array.prototype.reduce() to get your array, then Array.prototype.sort() to get the array with the most repititions.

let arr = ["5281-A", "5280-A", "5280-B", "5281-B"];
let arr2 = ["5281-A", "5280-B", "5281-B"];

// get the count of repititions
const getCountArray = (arr) => 
 Object.entries(
  arr.map((id) => id.split("-")[1]) // map the elements as "A" or "B"
   .reduce((a, c) => ((a[c] = (a[c] || 0) + 1), a), {})
 );

// return what is missing from two arrays
const whatIsMissing = (baseArray, secondArray) => {
  const [a, b] = [baseArray, secondArray].map(([[, a], [, b]]) => [a, b])
   .reduce(([a, b], [c, d]) => [a - c, b - d])
  
  return `A requires ${a} more, and B requires ${b} more`;
}

console.log(whatIsMissing(getCountArray(arr), getCountArray(arr2)))

Upvotes: 2

brk
brk

Reputation: 50346

You can use map

let arr = ["5281-A", "5280-A", "5280-B", "5281-B"]
let map = new Map();
arr.forEach((item) => {
  const txt = item.charAt(item.length - 1);
  if (!map.has(txt)) {
    map.set(txt, 1)
  } else {
    const val = map.get(txt);
    map.set(txt, val + 1)
  }
})
let newArr = [];
for (let [key, value] of map.entries()) {
  newArr.push([key, value])
};
console.log(newArr)

Upvotes: 1

fabrv
fabrv

Reputation: 382

The following code will achive your goal.

let arr = [ "5281-A", "5280-A", "5280-B", "5281-B" ]

let newObj = arr.reduce((a,b) => {
    const str = b.split('-')[1]
    a[str] = a[str] ? a[str] += 1 : 1
    return a
}, {})

This answer is better than using for-loops because it can be passed to a new object a lot easier.

Upvotes: 0

trincot
trincot

Reputation: 351369

You could split and then count. I opted to return a plain object (like you mentioned) in a function called countBySuffix.

Then I added another function, diff, which will compare two such objects (returned by countBySuffix) and will return only the differences. A difference is an array with three elements:

[suffix, count 1, count 2]

Where the suffix in your example would for example be "A", and the counts would be how many times this suffix appeared in the first input, and in the second input.

Snippet:

function countBySuffix(arr) {
  arr = arr.map(s => s.split("-").pop());
  let map = Object.fromEntries(arr.map(s => [s, 0]));
  for (let s of arr) map[s]++;
  return map;
}

function diff(a, b) {
  let res = [];
  for (let prop in a) {
    if (b[prop] != a[prop]) res.push([prop, a[prop], b[prop]]);
  }
  for (let prop in b) {
    if (!a[prop]) res.push([prop, undefined, b[prop]]);
  }
  return res;
}

// demo
let arr1 = [ "5281-A", "5280-A", "5280-B", "5281-B" ];
let arr2 = [ "5284-A", "5283-B", "5282-A"];

let count1 = countBySuffix(arr1);
let count2 = countBySuffix(arr2);

console.log(diff(count1, count2));

Upvotes: 1

Bulent
Bulent

Reputation: 3411

This should create an object:

let obj = {};
arr.forEach(item => {
 let letter = item.split("-")[1];
 obj[letter] = obj[letter] ? obj[letter] + 1 : 1;
})

output: {"A": 2, "B": 2}

If you need it in ["A", 2] format:

let outputArray = Object.entries(obj);

Upvotes: 0

Related Questions