Reputation: 359
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
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
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
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
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
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