Linear sorting of tree structured items [duplicate] - javascript

I would like to create a (non-anonymous) function that sorts an array of objects alphabetically by the key name. I only code straight-out JavaScript so frameworks don't help me in the least.
var people = [
{'name': 'a75', 'item1': false, 'item2': false},
{'name': 'z32', 'item1': true, 'item2': false},
{'name': 'e77', 'item1': false, 'item2': false}
];

How about this?
var people = [
{
name: 'a75',
item1: false,
item2: false
},
{
name: 'z32',
item1: true,
item2: false
},
{
name: 'e77',
item1: false,
item2: false
}];
function sort_by_key(array, key)
{
return array.sort(function(a, b)
{
var x = a[key]; var y = b[key];
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
});
}
people = sort_by_key(people, 'name');
This allows you to specify the key by which you want to sort the array so that you are not limited to a hard-coded name sort. It will work to sort any array of objects that all share the property which is used as they key. I believe that is what you were looking for?
And here is a jsFiddle: http://jsfiddle.net/6Dgbu/

You can sort an array ([...]) with the .sort function:
var people = [
{'name': 'a75', 'item1': false, 'item2': false},
{'name': 'z32', 'item1': true, 'item2': false},
{'name': 'e77', 'item1': false, 'item2': false},
];
var sorted = people.sort(function IHaveAName(a, b) { // non-anonymous as you ordered...
return b.name < a.name ? 1 // if b should come earlier, push a to end
: b.name > a.name ? -1 // if b should come later, push a to begin
: 0; // a and b are equal
});

This isn't a JSON question, per se. Its a javascript array question.
Try this:
people.sort(function(a,b){
var x = a.name < b.name? -1:1;
return x;
});

My solution for similar sort problem using ECMA 6
var library = [
{name: 'Steve', course:'WAP', courseID: 'cs452'},
{name: 'Rakesh', course:'WAA', courseID: 'cs545'},
{name: 'Asad', course:'SWE', courseID: 'cs542'},
];
const sorted_by_name = library.sort( (a,b) => a.name > b.name );
for(let k in sorted_by_name){
console.log(sorted_by_name[k]);
}

I modified #Geuis 's answer by using lambda and convert it upper case first:
people.sort((a, b) => a.toLocaleUpperCase() < b.toLocaleUpperCase() ? -1 : 1);

Array.prototype.sort_by = function(key_func, reverse=false){
return this.sort( (a, b) => ( key_func(b) - key_func(a) ) * (reverse ? 1 : -1) )
}
Then for example if we have
var arr = [ {id: 0, balls: {red: 8, blue: 10}},
{id: 2, balls: {red: 6 , blue: 11}},
{id: 1, balls: {red: 4 , blue: 15}} ]
arr.sort_by(el => el.id, reverse=true)
/* would result in
[ { id: 2, balls: {red: 6 , blue: 11 }},
{ id: 1, balls: {red: 4 , blue: 15 }},
{ id: 0, balls: {red: 8 , blue: 10 }} ]
*/
or
arr.sort_by(el => el.balls.red + el.balls.blue)
/* would result in
[ { id: 2, balls: {red: 6 , blue: 11 }}, // red + blue= 17
{ id: 0, balls: {red: 8 , blue: 10 }}, // red + blue= 18
{ id: 1, balls: {red: 4 , blue: 15 }} ] // red + blue= 19
*/

var data = [ 1, 2, 5, 3, 1];
data.sort(function(a,b) { return a-b });
With a small compartor and using sort, we can do it

This is how simply I sort from previous examples:
if my array is items:
0: {id: 14, auctionID: 76, userID: 1, amount: 39}
1: {id: 1086, auctionID: 76, userID: 1, amount: 55}
2: {id: 1087, auctionID: 76, userID: 1, amount: 55}
I thought simply calling items.sort() would sort it it, but there was two problems:
1. Was sorting them strings
2. Was sorting them first key
This is how I modified the sort function:
for(amount in items){
if(item.hasOwnProperty(amount)){
i.sort((a, b) => a.amount - b.amount);
}
}

var library = [
{name: 'Steve', course:'WAP', courseID: 'cs452'},
{name: 'Rakesh', course:'WAA', courseID: 'cs545'},
{name: 'Asad', course:'SWE', courseID: 'cs542'},
];
const sorted_by_name = library.sort( (a,b) => a.name > b.name );
for(let k in sorted_by_name){
console.log(sorted_by_name[k]);
}

var library = [
{name: 'Steve', course:'WAP', courseID: 'cs452'},
{name: 'Rakesh', course:'WAA', courseID: 'cs545'},
{name: 'Asad', course:'SWE', courseID: 'cs542'},
];
const sorted_by_name = library.sort( (a,b) => a.name > b.name ? 1:-1 );
for(let k in sorted_by_name){
console.log(sorted_by_name[k]);
}

var people =
[{"name": 'a75',"item1": "false","item2":"false"},
{"name": 'z32',"item1": "true","item2": "false"},
{"name": 'e77',"item1": "false","item2": "false"}];
function mycomparator(a,b) { return parseInt(a.name) - parseInt(b.name); }
people.sort(mycomparator);
something along the lines of this maybe (or as we used to say, this should work).

Related

Flatten whilst splitting into smaller objects

I am having these kind of array structure.
[{ "primary_product": "Blueberry",
"list_of_products": ["Raspberry","Strawberry","Blackberry"]}]
I want to destructure the pattern and make it like this below
[{"id": 1,"value":"Blueberry"},{"id": 2,"value":"Raspberry"},{"id": 3,"value":"Strawberry"}, …]
Primary product will be the first product and then make the array of strings into key/value pair. How to do this using es6?
All you need is basic functions like forEach and push. I would recommend learning these.
let arr1 = [{ "primary_product": "Blueberry", "list_of_products": ["Raspberry","Strawberry","Blackberry"]}]
arr2 = [{ id: 1, value: arr1[0].primary_product }]
arr1[0].list_of_products.forEach((element) => {
arr2.push({ id: arr2.length + 1, value: element })
})
Here's a one-liner using map on the list_of_products:
const arr = ['Raspberry','Strawberry','Blackberry'];
return arr.map((val, i) => {return {id: i+1, value: val}});
This is the result:
[
{ id: 1, value: 'Raspberry' },
{ id: 2, value: 'Strawberry' },
{ id: 3, value: 'Blackberry' }
]
Note that the callback to map includes (currentValue, index, arr).
To make things slightly easier for the eyes I've simplified the structure:
const p = [ { a: 100, b: [101, 102, 103]}
, { a: 200, b: [201, 202, 203]}];
You can flatten all the numbers into a single list i.e. [100, 101, 102, 103, 200, 201, 202, 203] with:
p.flatMap(({a, b}) => [a, ...b]);
To get closer to what you're after, let's first create an id function that will return the next number:
const id = (n => () => ++n)(0);
id(); //=> 1
id(); //=> 2
id(); //=> 3
// …
Then let's create a function obj that takes an x and wraps it into an object:
const obj => x => ({id: id(), value: x});
obj(100); //=> {id: 1, value: 100);
obj(200); //=> {id: 2, value: 200);
// …
Then you can do:
p.flatMap(({a, b}) => [obj(a), ...b.map(obj)]);
//=> [ {id: 1, value: 100}
//=> , {id: 2, value: 101}
//=> , {id: 3, value: 102}
//=> , {id: 4, value: 103}
//=> , {id: 5, value: 200}
//=> , {id: 6, value: 201}
//=> , {id: 7, value: 202}
//=> , {id: 8, value: 203}]

Filter array of objects with sub arrays

I have next array:
const arr = [
{
id: 1,
food: ['cola', 'pizza pie'],
size: [{value: 12}, {value: 14}],
},
{
id: 2,
food: ['water', 'wine', 'pasta'],
size: [{value: 15}, {value: 19}],
},
{
id: 3,
food: ['water', 'wine', 'pasta'],
size: [{value: 1}, {value: 13}],
},
];
I need to filter this array in the next way:
If I have the same 'food' values, the array item which has the highest 'size->value', should left, other removed.
Expected result:
const arr = [
{
id: 1,
food: ['cola', 'pizza pie'],
size: [{value: 12}, {value: 14}],
},
{
id: 2,
food: ['water', 'wine', 'pasta'],
size: [{value: 15}, {value: 19}],
},
];
What is the best way for this?
Your requirement as a little vague - particularly when you said:
If I have the same 'food' values, the array item which has the highest 'size->value', should left, other removed.
But here is an approach using Array.prototype.reduce (assuming the comparison is between the total sum of size values when duplicates are found). I've commented the code to give an idea on what's happening.
const arr = [{
id: 1,
food: ['cola', 'pizza pie'],
size: [{
value: 12
}, {
value: 14
}],
},
{
id: 2,
food: ['water', 'wine', 'pasta'],
size: [{
value: 15
}, {
value: 19
}],
},
{
id: 3,
food: ['water', 'wine', 'pasta'],
size: [{
value: 1
}, {
value: 13
}],
},
];
function process(arr) {
return arr.reduce((acc, curr) => {
const item = acc.filter(x => curr.food.sort().toString() === x.food.sort().toString()) // check if there is another entry with the same `food` value
if (item.length) {
// comparision logic goes here
const previousSizes = item[0].size.reduce((a, b) => a + b.value, 0) // previous item's total size
const currentSizes = curr.size.reduce((a, b) => a + b.value, 0) // current item's total size
if (currentSizes > previousSizes) {
return [...acc.filter(x => x !== item[0]), curr] //remove the previous item and add the new one
} else return acc // don't change
} else return [...acc, curr] // curr is a new item.. so just add it
}, [])
}
console.log(process(arr))
The following sorts the input by food items to gather similar items together. It then walks the sorted input deleting items as it finds new maximums. It records the current maximum for each food grouping in a hashtable.
I think time complexity is n log(n) and the space complexity is n.
This implementation assumes the largest value in each size array is what you care about.
Pseudocode:
00. Create hashtable `hash`
01. Sort array `arr` by food
02. For each item `i` in `arr`
03. Let `key` be a unique key for `i` based on food
04. Let `largestSize` be the largest number in `i.size`
05. if `hash` does not contain `key`
06. Set value of `key` in `hash` to `largestSize`
07. else
08. if `largestSize` is larger than hash.key
09. replace `m` and delete previous item in `arr` because current item is larger
10. else
11. delete current item in `arr` because it is too small
12. end if
13. end if
14. end for
15. return `arr`
function filter(arr) {
const hash = {}
arr.sort(({food: a},{food: b})=>String(a).localeCompare(String(b)))
for (let x = 0; x < arr.length; x++) {
const {food, size} = arr[x]
const [{ value: largestSize }] = size.sort(({value: a},{value: b})=>a - b).slice(-1)
const key = String(food)
if (!hash[key])
hash[key] = largestSize
else {
if (largestSize > hash[key]) {
arr.splice(x - 1, 1)
hash[key] = largestSize
} else
arr.splice(x, 1)
--x
}
}
return arr
}
const arr = [
{
id: 1,
food: ['cola', 'pizza pie'],
size: [{value: 12}, {value: 14}],
},
{
id: 2,
food: ['water', 'wine', 'pasta'],
size: [{value: 15}, {value: 19}],
},
{
id: 3,
food: ['water', 'wine', 'pasta'],
size: [{value: 1}, {value: 13}],
},
]
console.log(filter(arr))

Filter and create a new array [duplicate]

This question already has answers here:
Using array map to filter results with if conditional
(5 answers)
Map and filter an array at the same time
(16 answers)
Closed 3 years ago.
I have an object as shown below:
var obj = [
{id: 1, name: 'AD', key: 10},
{id: 2, name: 'AD', key: 20},
{id: 3, name: 'BD', key: 30},
{id: 4, name: 'CD', key: 40}
];
I want to filter and create a new array which satisfies any condition. For eg: filter which have name as 'AD' and create a new array of key as:
[10, 20]
Tried .map
obj.map(ele => {
return ele.name === 'AD' ? ele.key : null;
}); //it adds even nulls in the result array as [10, 20, null, null]
Tried .filter:
obj.filter(ele => {
return ele.name === 'AD' ? ele.key : null;
});
Result: [{id: 1, name: "AD", key: 10}, {id: 2, name: "AD", key: 20}] //gives array of objects, not what I'm expecting.
Thanks in advance
First filter the array and then map to get the value:
obj.filter(e => e.name === 'AD').map(e => e.key)
Another option is flatmap (check browser compatibility here)
obj.flatMap(e => e.name === 'AD' ? [e.key] : [])
First of all obj is an array in your code.
Now the solution is simple you filter first and then map like this:
obj.filter(item => item.name === 'AD').map(item => item.key);
You can use reduce():
var obj = [{id: 1, name: 'AD', key: 10},{id: 2, name: 'AD', key: 20},{id: 3, name: 'BD', key: 30},{id: 4, name: 'CD', key: 40}];
var result = obj.reduce((acc, cur) => {
if (cur.name == "AD") acc.push(cur.key)
return acc;
}, []);
console.log(result);
var obj = [
{id: 1, name: 'AD', key: 10},
{id: 2, name: 'AD', key: 20},
{id: 3, name: 'BD', key: 30},
{id: 4, name: 'CD', key: 40}
];
function specialFilter(filt) {
return obj.filter(el => el.name === filt).map(el => el.key)
}
console.log(specialFilter("AD"))

how to sort an array of objects with different keys

I'm trying to sort an array of objects by a key in a particular position. The only problem is that each object has a different key name.
here is an example of an object i'm trying to sort:
let data = [
{name: "James", x: 3, },
{name: "Thomas", y: 1},
{name: "Zack", z: 2}
];
I'm trying to sort it by the 2nd key so the order should be
[
{name: "James", x: 3, },
{name: "Zack", z: 2},
{name: "Thomas", y: 1}
];
here is how I'm trying to do it:
let data = [
{name: "James", x: 3, },
{name: "Thomas", y: 1},
{name: "Zack", z: 2}
];
data.sort((a, b) => {
let key1 = Object.keys(a)[1];
let key2 = Object.keys(b)[1];
return a[key1] > b[key2]
});
console.log(data)
Here is my jsbin
https://jsbin.com/lihefodoni/edit?html,js,console
Not sure why it's not working. I'm trying to do this in my react Application so I don't know if there's something different I need to do?
The .sort callback expects a number as a return value, not a Boolean (as the < operator will evaluate to). Return the numeric difference instead:
let data = [
{name: "James", x: 3, },
{name: "Thomas", y: 1},
{name: "Zack", z: 2}
];
data.sort((a, b) => {
let key1 = Object.keys(a)[1];
let key2 = Object.keys(b)[1];
return b[key2] - a[key1]
});
console.log(data)
To make sorting more reliable, .find the entry whose key is not name:
let data = [
{name: "James", x: 3, },
{name: "Thomas", y: 1},
{name: "Zack", z: 2}
];
data.sort((a, b) => {
const aEntry = Object.entries(a).find(([key]) => key !== 'name');
const bEntry = Object.entries(b).find(([key]) => key !== 'name');
return bEntry[1] - aEntry[1];
});
console.log(data)
You could exclude the unwanted key and take the values of the object. it works by taking the only item without index.
let data = [{ name: "James", x: 3 }, { name: "Thomas", y: 1 }, { name: "Zack", z: 2 }];
data.sort(({ name, ...a }, { name: _, ...b }) => Object.values(b) - Object.values(a));
console.log(data)
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sorting large array into simpler one [duplicate]

This question already has answers here:
Most efficient method to groupby on an array of objects
(58 answers)
Closed 4 years ago.
What would be the best way to sort myarr into sortedArr so that all of the values have been added together for each invidual id using javascript?
myarr = [{id: 10, val:100}, {id:10, val: 100}, {id:20, val:200}, {id:20, val:100}, {id:30, val:100}]
sortedArr = [{id: 10, val: 200}, {id:20, val:300}, {id:30, 100}]
First sum the values per ID, then push them to a new array.
let myarr = [{ id: 10, val: 100 }, { id: 10, val: 100 }, { id: 20, val: 200 }, { id: 20, val: 100 }, { id: 30, val: 100 }]
let group = {}
myarr.forEach((value, index) => {
if (group[value.id]) {
group[value.id] += value.val
}
else {
group[value.id] = value.val
}
})
let res = []
Object.keys(group).forEach((key) => {
res.push({ id: key, val: group[key] })
})
console.log(res);
You need to keep a map of keys (hits) and reduce the original array. You can sort it afterwards, because the array will be smaller which speeds up sorting.
var myArr = [{id: 10, val:100}, {id:10, val: 100}, {id:20, val:200}, {id:20, val:100}, {id:30, val:100}];
var sortedArr = accumulateAndSortById(myArr, 'id', 'val');
console.log(sortedArr);
function accumulateAndSortById(arr, field, value) {
var hitMap = arr.reduce((result, item) => {
result[item[field]] = (result[item[field]] || 0) + item[value];
return result;
}, {});
return Object.keys(hitMap).reduce((result, key) => {
var obj = {};
obj[key] = hitMap[key];
result.push(obj);
return result;
}, []).sort((a, b) => a[field] > b[field]);
}
.as-console-wrapper { top: 0; max-height: 100% !important; }
You can do:
const myArr = [{id: 10, val:100}, {id:10, val: 100}, {id:20, val:200}, {id:20, val:100}, {id:30, val:100}]
const temp = myArr.reduce((a, c) => (a[c.id] = (a[c.id] || 0) + c.val, a), {});
const sortedArr = Object.keys(temp).map(k => ({id: +k, val: temp[k]}));
console.log(sortedArr);
Use the following compare function to sort:
var myArr = [{id: 10, val:100}, {id:10, val: 100}, {id:20, val:200}, {id:20, val:100}, {id:30, val:100}];
function compare(a,b) {
if (a.id < b.id)
return -1;
if (a.id > b.id)
return 1;
return 0;
}
var sortedArr = myArr.sort(compare);

Categories