How to sort an array by frequency of occurrence? - javascript

I've array like this :
people = [
{id:1,name:'abc',age:18},
{id:2,name:'abcd',age:20},
{id:3,name:'abce',age:18},
{id:4,name:'abcf',age:18},
{id:5,name:'abcg',age:21},
{id:6,name:'abch',age:20},
{id:7,name:'abci',age:17},
]
Now I want Sorting an array order by frequency of occurence(age) in JavaScript.
Output like this:
people = [
{id:1,name:'abc',age:18},
{id:3,name:'abce',age:18},
{id:4,name:'abcf',age:18},
{id:2,name:'abcd',age:20},
{id:6,name:'abch',age:20},
{id:5,name:'abcg',age:21},
{id:7,name:'abci',age:17},
]
So how I can do it ?
I've tried follow answer of Nina Scholz but i've a bug like this.
var people = [{ id: 1, name: 'abc', age: 18 }, { id: 2, name: 'abcd', age: 20 }, { id: 3, name: 'abce', age: 18 }, { id: 4, name: 'abcf', age: 18 }, { id: 5, name: 'abcg', age: 21 }, { id: 6, name: 'abch', age: 20 }, { id: 7, name: 'abcg', age: 21 }, { id: 8, name: 'abci', age: 17 }],
count = people.reduce((r, { age }) => (r[age] = (r[age] || 0) + 1, r), {});
people.sort((a, b) => count[b.age] - count[a.age]);
console.log(people);
Output is :
people = [
{id:1,name:'abc',age:18},
{id:3,name:'abce',age:18},
{id:4,name:'abcf',age:18},
{id:2,name:'abcd',age:20},
{id:5,name:'abcg',age:21},
{id:6,name:'abch',age:20},
{id:5,name:'abcg',age:21},
{id:7,name:'abci',age:17},
]

Just count ages and sort descending by the count.
var people = [{ id: 1, name: 'abc', age: 18 }, { id: 2, name: 'abcd', age: 20 }, { id: 3, name: 'abce', age: 18 }, { id: 4, name: 'abcf', age: 18 }, { id: 5, name: 'abcg', age: 21 }, { id: 6, name: 'abch', age: 20 }, { id: 7, name: 'abci', age: 17 }],
count = people.reduce((r, { age }) => (r[age] = (r[age] || 0) + 1, r), {});
people.sort((a, b) => count[b.age] - count[a.age]);
console.log(people);
.as-console-wrapper { max-height: 100% !important; top: 0; }
For sorting by count and age, add a logical OR || along with the delta of the ages.
var people = [{ id: 1, name: 'abc', age: 18 }, { id: 2, name: 'abcd', age: 20 }, { id: 3, name: 'abce', age: 18 }, { id: 4, name: 'abcf', age: 18 }, { id: 5, name: 'abcg', age: 21 }, { id: 6, name: 'abch', age: 20 }, { id: 7, name: 'abcg', age: 21 }, { id: 8, name: 'abci', age: 17 }],
count = people.reduce((r, { age }) => (r[age] = (r[age] || 0) + 1, r), {});
people.sort((a, b) =>
count[b.age] - count[a.age] ||
b.age - a.age
);
console.log(people);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Try this:
let people = [{ id: 1, name: 'abc', age: 18 }, { id: 2, name: 'abcd', age: 20 }, { id: 3, name: 'abce', age: 18 }, { id: 4, name: 'abcf', age: 18 }, { id: 5, name: 'abcg', age: 21 }, { id: 6, name: 'abch', age: 20 }, { id: 7, name: 'abci', age: 17 }];
let tmpAge = {};
for (let i = 0; i < people.length; i++) {
if (!tmpAge[people[i].age]) {
tmpAge[people[i].age] = 1;
} else {
tmpAge[people[i].age]++;
}
}
people.sort((a, b) => tmpAge[b.age] - tmpAge[a.age]);
console.log(people);

const people = [
{ id: 1, name: 'abc', age: 18 },
{ id: 2, name: 'abcd', age: 20 },
{ id: 3, name: 'abce', age: 18 },
{ id: 4, name: 'abcf', age: 18 },
{ id: 5, name: 'abcg', age: 21 },
{ id: 6, name: 'abch', age: 20 },
{ id: 7, name: 'abci', age: 17 },
];
const agesFrequency = people.reduce((previousValue, currentValue) => {
const { age } = currentValue;
return {
...previousValue,
[age]: (
previousValue[age] || 0
) + 1,
};
}, {});
people.sort((
(a, b) =>
agesFrequency[b.age] - agesFrequency[a.age]
));
console.log(people);

I solved it . Change function sort to
people.sort((a, b) => {
if (count[b.age] === count[a.age]) {
if (b.age < a.age) {
return -1;
}
if (b.age > a.age) {
return 1;
}
return 0;
} else if (count[b.age] < count[a.age]) {
return -1;
}
});
Posted on behalf of OP

Related

How to push some arrays to the main array in angular 8

Hi i am working on Angular 7 and I have 3 main arrays fetching from API like mentioned in stackblitz
And now the 3 main arrays look like this.
this.mainarr = [
{ id: 1, name: "Praveen", age: 3, color: 3 },
{ id: 2, name: "kumar", age: 2, color: 4 },
{ id: 3, name: "john", age: 4, color: 2 },
{ id: 4, name: "alex", age: 5, color: 1 },
{ id: 5, name: "profes", age: 3, color: 2 }
];
this.agearr = [
{ id: 1, age: 22 },
{ id: 2, age: 24 },
{ id: 3, age: 33 },
{ id: 4, age: 12 },
{ id: 5, age: 26 }
];
this.colorarr = [
{ id: 1, color: "black" },
{ id: 2, color: "paleblack" },
{ id: 3, color: "brown" },
{ id: 4, color: "white" },
{ id: 5, color: "greyish" }
];
So, in the mainarr i have ids and the agearr and colorarr id matched i need a different key value pair in mainarr and display that values.
so my expected result should be
[
{ id: 1, name: "Praveen", age: 3, color: 3,agename: 33,colorname: 'brown'},
{ id: 2, name: "kumar", age: 2, color: 4,agename: 24,colorname: 'white'},
{ id: 3, name: "john", age: 4, color: 2 agename: 12,colorname:'paleblack'},
{ id: 4, name: "alex", age: 5, color: 1 agename: 26,colorname:'black'},
{ id: 5, name: "profes", age: 3, color: 2 agename: 33,colorname:'paleblack'}
];
I am getting the desired result but only after page refresh how to do it any idea?TIA
Here is the updated stackblitz
In the if block you were checking for the wrong property. Corrected it.
if (this.mainarr[i].age == this.agearr[j].id)
Try like following:
getFunction() {
this.mainarr.map(x => {
x["agename"] = this.agearr.find(y => y.id == x.age)["age"];
x["colorname"] = this.colorarr.find(y => y.id == x.color)["color"];
});
console.log(this.mainarr);
}
Working Stackbllitz Example: https://stackblitz.com/edit/angular-ivy-ve5cdp?file=src/app/app.component.ts

Javascript - How to create filtered nested Array

I have my array object here:
let businessList = [{
name: "siAdmin",
count: 52,
children: [{
name: "si1",
count: 30,
children: [{
count: 10,
name: "org1-1"
}, {
count: 14,
name: "org1-2"
}, {
name: "org1-3",
count: 6
}]
}, {
name: "si2",
count: 22,
children: [{
name: "org2-1",
count: 22
}]
}]
}]
I want to make make a filtered list if count > 10, which would be like:
filteredList = [{
name: "siAdmin",
count: 52,
children: [{
name: "si1",
count: 30,
children: [{
count: 14,
name: "org1-2"
}]
}, {
name: "si2",
count: 22,
children: [{
name: "org2-1",
count: 22
}]
}]
}]
How can I achieve this result?
And if condition changes to count > 23, it would be like:
filteredList = [{
name: "siAdmin",
count: 52,
children: [{
name: "si1",
count: 30,
children: []
}]
}]
You can use recursion like this,
let businessList = [{
name: "siAdmin",
count: 52,
children: [{
name: "si1",
count: 30,
children: [{
count: 10,
name: "org1-1"
}, {
count: 14,
name: "org1-2"
}, {
name: "org1-3",
count: 6
}]
}, {
name: "si2",
count: 22,
children: [{
name: "org2-1",
count: 22
}]
}]
}];
const filteredArray = (arr, countLimit) => {
return arr.filter(item => {
if(item.hasOwnProperty('children')) {
item.children = filteredArray(item.children, countLimit);
}
return item.count > countLimit;
})
};
console.log(filteredArray(JSON.parse(JSON.stringify(businessList)), 10));
console.log(filteredArray(JSON.parse(JSON.stringify(businessList)), 23));
console.log(businessList);
let businessList = [{
name: "siAdmin",
count: 52,
children: [{
name: "si1",
count: 30,
children: [{
count: 10,
name: "org1-1"
}, {
count: 14,
name: "org1-2"
}, {
name: "org1-3",
count: 6
}]
}, {
name: "si2",
count: 22,
children: [{
name: "org2-1",
count: 22
}]
}]
}]
function getData(input, number){
let len = input.length;
let ans = [];
for(let i = 0; i < len; i++){
if(input[i].count >= number){
if(input[i].children){
let data = getData(input[i].children,number);
//ans.push(input[i]);
input[i].children = data;
ans.push(input[i])
}
else{
ans.push(input[i]);
}
}
}
return ans;
}
getData(businessList,10)
getData(businessList,23)
above function should work
I finally find the solution without breaking the original object, here's my code:
let businessList = [{
name: "siAdmin",
count: 52,
children: [{
name: "si1",
count: 30,
children: [{
count: 10,
name: "org1-1"
}, {
count: 14,
name: "org1-2"
}, {
name: "org1-3",
count: 6
}]
}, {
name: "si2",
count: 22,
children: [{
name: "org2-1",
count: 22
}]
}]
}];
function filteredBusiness(businessArr, count) {
let arr = [];
businessArr.forEach((business) => {
let index = 0;
let businessMatched = business.count > count
if (businessMatched) {
let {
children,
...dataWithoutChildren
} = business;
arr.push({
...dataWithoutChildren
});
index = arr.length - 1;
let hasChildren = business.children;
if (hasChildren) {
// arr[index].children = [];
//check children matched
let nextBusinessArr = filteredBusiness(
business.children,
count
);
if (nextBusinessArr) {
arr[index].children = nextBusinessArr;
}
}
}
})
return arr;
}
console.log(filteredBusiness(businessList, 10))

How would I compare the two to properly sort in order?

Objective is to distinguish the two arrays, and console log the products array in order by its price range, I tried using a nested for-loop to see if this can work out but hasn't gone off in the right track, was also thinking about using lo dash as well. How would I be able to compare the id's between the two and push them in order by price?
/*
Your task is to write a function or set of functions that console logs out the products ordered by price
*/
var products = [
{ id: 1, name: 'Buzzy' },
{ id: 2, name: 'Bytrex' },
{ id: 3, name: 'CactiDance' },
{ id: 4, name: 'CactiLoops' },
{ id: 5, name: 'Cadaver Jelly' },
{ id: 6, name: 'Caffeine Serene' },
{ id: 7, name: 'Cajun Sation' },
{ id: 8, name: 'Call it Green' },
{ id: 9, name: 'Callflex' },
{ id: 10, name: 'Calling Card Shark' },
{ id: 11, name: 'Calque' },
{ id: 12, name: 'Camel Meal Tea' },
{ id: 13, name: 'Camelot Chamomile' },
{ id: 14, name: 'Campxotica' },
{ id: 15, name: 'Camus the Killer Tale' },
{ id: 16, name: 'Candecor' },
{ id: 17, name: 'Candelarium' },
{ id: 18, name: 'CandID' },
{ id: 19, name: 'Candlelight Vittles' },
{ id: 20, name: 'Candy Ask' },
{ id: 21, name: 'Candy Floss' },
];
var prices = [
{ id: 6, price: 55 },
{ id: 14, price: 22 },
{ id: 15, price: 57 },
{ id: 4, price: 41 },
{ id: 18, price: 9 },
{ id: 17, price: 3 },
{ id: 2, price: 73 },
{ id: 7, price: 43 },
{ id: 5, price: 78 },
{ id: 1, price: 91 },
{ id: 8, price: 58 },
{ id: 16, price: 69 },
{ id: 13, price: 74 },
{ id: 19, price: 14 },
{ id: 21, price: 25 },
{ id: 12, price: 84 },
{ id: 20, price: 8 },
{ id: 9, price: 94 },
{ id: 10, price: 36 },
{ id: 3, price: 34 },
{ id: 11, price: 71 },
];
You can use map & findIndex. map will return a new array. Inside the callback function of map use findIndex and use it to find the index of the object where the id matches.
var products = [{
id: 1,
name: 'Buzzy'
},
{
id: 2,
name: 'Bytrex'
},
{
id: 3,
name: 'CactiDance'
},
{
id: 4,
name: 'CactiLoops'
},
{
id: 5,
name: 'Cadaver Jelly'
},
{
id: 6,
name: 'Caffeine Serene'
},
{
id: 7,
name: 'Cajun Sation'
},
{
id: 8,
name: 'Call it Green'
},
{
id: 9,
name: 'Callflex'
},
{
id: 10,
name: 'Calling Card Shark'
},
{
id: 11,
name: 'Calque'
},
{
id: 12,
name: 'Camel Meal Tea'
},
{
id: 13,
name: 'Camelot Chamomile'
},
{
id: 14,
name: 'Campxotica'
},
{
id: 15,
name: 'Camus the Killer Tale'
},
{
id: 16,
name: 'Candecor'
},
{
id: 17,
name: 'Candelarium'
},
{
id: 18,
name: 'CandID'
},
{
id: 19,
name: 'Candlelight Vittles'
},
{
id: 20,
name: 'Candy Ask'
},
{
id: 21,
name: 'Candy Floss'
},
];
var prices = [{
id: 6,
price: 55
},
{
id: 14,
price: 22
},
{
id: 15,
price: 57
},
{
id: 4,
price: 41
},
{
id: 18,
price: 9
},
{
id: 17,
price: 3
},
{
id: 2,
price: 73
},
{
id: 7,
price: 43
},
{
id: 5,
price: 78
},
{
id: 1,
price: 91
},
{
id: 8,
price: 58
},
{
id: 16,
price: 69
},
{
id: 13,
price: 74
},
{
id: 19,
price: 14
},
{
id: 21,
price: 25
},
{
id: 12,
price: 84
},
{
id: 20,
price: 8
},
{
id: 9,
price: 94
},
{
id: 10,
price: 36
},
{
id: 3,
price: 34
},
{
id: 11,
price: 71
},
];
let newArr = prices.map(function(item) {
let k = products.findIndex(elem => elem.id === item.id);
if (k !== -1) {
return products[k]
}
});
console.log(newArr)
You could sort the prices array first. Then loop through it and get the products for each id using find like this:
var products = [{id:1,name:"Buzzy"},{id:2,name:"Bytrex"},{id:3,name:"CactiDance"},{id:4,name:"CactiLoops"},{id:5,name:"Cadaver Jelly"},{id:6,name:"Caffeine Serene"},{id:7,name:"Cajun Sation"},{id:8,name:"Call it Green"},{id:9,name:"Callflex"},{id:10,name:"Calling Card Shark"},{id:11,name:"Calque"},{id:12,name:"Camel Meal Tea"},{id:13,name:"Camelot Chamomile"},{id:14,name:"Campxotica"},{id:15,name:"Camus the Killer Tale"},{id:16,name:"Candecor"},{id:17,name:"Candelarium"},{id:18,name:"CandID"},{id:19,name:"Candlelight Vittles"},{id:20,name:"Candy Ask"},{id:21,name:"Candy Floss"}],
prices = [{id:6,price:55},{id:14,price:22},{id:15,price:57},{id:4,price:41},{id:18,price:9},{id:17,price:3},{id:2,price:73},{id:7,price:43},{id:5,price:78},{id:1,price:91},{id:8,price:58},{id:16,price:69},{id:13,price:74},{id:19,price:14},{id:21,price:25},{id:12,price:84},{id:20,price:8},{id:9,price:94},{id:10,price:36},{id:3,price:34},{id:11,price:71}];
prices.sort((a, b) => a.price - b.price)
.forEach(p => {
console.log(products.find(a => a.id === p.id))
})

Typescript - Rearrange specific object

I've arranged object in alphabetical order. I wanna move "Others" at last in dropdown. Is there any way to acheive this?
this.registrationMerchantService.getBusinessCategories().subscribe(response => {
this.businessCategories = response;
this.businessCategories.sort(function(a, b) {
if (a.name < b.name) {
return -1;
}
if (a.name > b.name) {
return 1;
}
return 0;
});
});
Json objects
export const BUSINESS_CATEGORIES: BusinessCategory[] = [
{ id: 1, name: 'Food & Beverage' },
{ id: 2, name: 'Transportation & Travel' },
{ id: 3, name: 'Fashion' },
{ id: 4, name: 'Leisure' },
{ id: 5, name: 'Digital Content' },
{ id: 6, name: 'Health and Beauty' },
{ id: 7, name: 'Online Shopping' },
{ id: 8, name: 'Telecommunications' },
{ id: 9, name: 'Utilities' },
{ id: 10, name: 'Others' },
{ id: 11, name: 'General' },
{ id: 12, name: 'Insurance' },
{ id: 13, name: 'Services' },
{ id: 14, name: 'Appliances' },
{ id: 15, name: 'Entertainment' },
{ id: 16, name: 'Household Goods & Groceries' },
];
Current result:
Is there any idea to move "Others" at last in the dropdown list
You can try sorting the array filtering out "Others" and then add it at the end:
var categories = [
{ id: 1, name: 'Food & Beverage' },
{ id: 2, name: 'Transportation & Travel' },
{ id: 3, name: 'Fashion' },
{ id: 4, name: 'Leisure' },
{ id: 5, name: 'Digital Content' },
{ id: 6, name: 'Health and Beauty' },
{ id: 7, name: 'Online Shopping' },
{ id: 8, name: 'Telecommunications' },
{ id: 9, name: 'Utilities' },
{ id: 10, name: 'Others' },
{ id: 11, name: 'General' },
{ id: 12, name: 'Insurance' },
{ id: 13, name: 'Services' },
{ id: 14, name: 'Appliances' },
{ id: 15, name: 'Entertainment' },
{ id: 16, name: 'Household Goods & Groceries' },
];
const sorted = categories.sort(function(a, b) {
if (a.name < b.name) {
return -1;
}
if (a.name > b.name) {
return 1;
}
return 0;
});
console.log(
sorted
.filter(x=>x.name!=="Others")//remove "Others"
.concat(sorted.find(x=>x.name==="Others"))//add "Others" at the end
);
You can create a function that accepts an ignore list, and you can return a sorting function that takes care of ignoring certain names, by placing them above or below in the list.
You can fiddle with the sorting direction to get the desired result.
var BUSINESS_CATEGORIES = [
{ id: 1, name: 'Food & Beverage' },
{ id: 2, name: 'Transportation & Travel' },
{ id: 3, name: 'Fashion' },
{ id: 4, name: 'Leisure' },
{ id: 5, name: 'Digital Content' },
{ id: 6, name: 'Health and Beauty' },
{ id: 7, name: 'Online Shopping' },
{ id: 8, name: 'Telecommunications' },
{ id: 9, name: 'Utilities' },
{ id: 10, name: 'Others' },
{ id: 11, name: 'General' },
{ id: 12, name: 'Insurance' },
{ id: 13, name: 'Services' },
{ id: 14, name: 'Appliances' },
{ id: 15, name: 'Entertainment' },
{ id: 16, name: 'Household Goods & Groceries' },
];
let categories = this.BUSINESS_CATEGORIES.sort(customSort([ 'Others' ], 1));
console.log(JSON.stringify(categories, null, 2));
function customSort(ignoreList, direction) {
ignoreList = ignoreList || [];
direction = direction || 1;
return function(a, b) {
var aPos = ignoreList.indexOf(a.name);
var bPos = ignoreList.indexOf(b.name);
if (bPos > -1) return -1 * direction;
if (aPos > -1) return 1 * direction;
return a.name.localeCompare(b.name) * direction;
}
}
.as-console-wrapper { top: 0; max-height: 100% !important; }

Grouping array by same property value, iterate over that array

I have the following array:
var results = [
{ group: 1,
department: 2,
total: 10 },
{ group: 1,
department: 2,
total: 25 },
{ group: 1,
department: 3,
total: 15 },
{ group: 1,
department: 3,
total: 5 },
{ group: 2,
department: 4,
total: 10},
{ group: 2,
department: 4,
total: 50 }
]
I need to arrange the array into a 2D nested array, where the sub arrays are Group 1 and Group 2. The sub arrays should also be parent arrays, whose children are ordered by Department, like so:
var results:[
{
group1:[
{
department2:[
{
group:1,
department:2,
total:10
},
{
group:1,
department:2,
total:25
},
{
group:1,
department:3,
total:15
}
]
},
{
department3:[
{
group:1,
department:3,
total:5
}
]
}
]
},
{
group2:[
{
department4:[
{
group:2,
department:4,
total:10
},
{
group:2,
department:4,
total:50
}
]
}
]
}
]
This is for a react component, where I need to print each one as a row, but add a total after all the department groups are done, and then one after each group, and then a total after everything.
Perhaps I´m over complicating it and there is a better way?
var results = [
{ group: 1,
department: 2,
total: 10 },
{ group: 1,
department: 2,
total: 25 },
{ group: 1,
department: 3,
total: 15 },
{ group: 1,
department: 3,
total: 5 },
{ group: 2,
department: 4,
total: 10},
{ group: 2,
department: 4,
total: 50 }
]
var nested_result = {}
results.forEach(obj => {
if(nested_result[obj.group] === undefined) {
nested_result[obj.group] = {};
}
if(nested_result[obj.group][obj.department] === undefined) {
nested_result[obj.group][obj.department] = [];
}
nested_result[obj.group][obj.department].push(obj);
})
console.log(nested_result);
var results = [
{ group: 1, department: 2, total: 10 },
{ group: 1, department: 2, total: 25 },
{ group: 1, department: 3, total: 15 },
{ group: 1, department: 3, total: 5 },
{ group: 2, department: 4, total: 10},
{ group: 2, department: 4, total: 50 }
]
var outObj = {};
var out = results.map(function(a) {
var groupName = 'group' + a.group;
typeof outObj[groupName] == 'undefined' && ( outObj[groupName] = {});
var depName = 'department' + a.department;
typeof outObj[groupName][depName] == 'undefined' && ( outObj[groupName][depName] = [] );
outObj[groupName][depName].push(a );
});
console.log( outObj );

Categories

Resources