Related
I want to get the largest object in an array of objects, the code I'm using works fine, but I wonder if there is a better way of doing the same. This is the code I'm using.
data=[
{group: "a", A: 65, N: 20},
{group: "b", R: 52},
{group: "c", N: 20, A: 2, R: 2},
{group: "d", R: 15, N: 12},
]
len = []
for (var i in data){
len.push(Object.keys(data[i]).length)
}
for (var i in data){
if (Object.keys(data[i]).length==Math.max.apply(null, len)){
subgroups = Object.keys(data[i]).slice(1).sort();
}
}
console.log(subgroups);
I think one loop is sufficient to do this.
var data=[
{group: "a", A: 65, N: 20},
{group: "b", R: 52},
{group: "c", N: 20, A: 2, R: 2},
{group: "d", R: 15, N: 12},
],
max = Object.keys(data[0]).length,
largestObj = data[0];
data.forEach(i=>{
if(Object.keys(i).length> max){
max = Object.keys(i).length;
largestObj = i;
}
});
console.log(max);
console.log(largestObj);
An example using Array.prototype.reduce
const [biggestObject] = data.reduce(
([acc, length], entry) => {
const len = Object.keys(entry).length;
return length > len ? [acc, length] : [entry, len];
},
[{}, 0]
);
To sort the whole array seems stupid, one loop is enough using reduce function
const { element } = data.reduce((agg, element) => {
const length = Object.keys(v).length
if (length > agg.length) {
return { element, length }
}
return agg
}, { element: null, length: 0 })
You can just sort the array using the criteria you used for filling the len array.
data.sort((x, y) => {
return Object.keys(y).length - Object.keys(x).length
});
Result:
0: {group: "c", N: 20, A: 2, R: 2}
1: {group: "a", A: 65, N: 20}
2: {group: "d", R: 15, N: 12}
3: {group: "b", R: 52}
Let's say I have an array of objects:
var list = [
{ name: "A", distance: 1},
{ name: "B", distance: 2},
{ name: "C", distance: 3},
{ name: "D", distance: 4},
{ name: "E", distance: 5},
{ name: "F", distance: 6},
{ name: "G", distance: 7},
{ name: "H", distance: 8}
];
if I have another array like this one :
var disturbed = ["G", "B", "C", "F"];
how can I sort disturbed array based on distance property from the list array like this:
["B", "C", "F", "G"];
Edit: I have tried this code with no success:
items = [
{ name: "A", distance: 1},
{ name: "B", distance: 2},
{ name: "C", distance: 3},
{ name: "D", distance: 4},
{ name: "E", distance: 5},
{ name: "F", distance: 6},
{ name: "G", distance: 7},
{ name: "H", distance: 8}
]
sorting = [ 1, 2,3,4,5,6,7,8,9,10 ];
result = []
for (let i = 0; i < items.length; i++){
sorting.forEach(function(key) {
var found = false;
items = items.filter(function(item) {
if(!found && items[i].distance == key) {
result.push(item);
found = true;
return false;
} else
return true;
})
})
result.forEach(function(item) {
document.writeln(item[i])
})
}
How can I Sort an array based on the property value of another array of objects
You can use .reduce() to change the list array to object and then sort based on this object.
Demo:
var list = [
{ name: "A", distance: 1},
{ name: "B", distance: 2},
{ name: "C", distance: 3},
{ name: "D", distance: 4},
{ name: "E", distance: 5},
{ name: "F", distance: 6},
{ name: "G", distance: 7},
{ name: "H", distance: 8}
];
var disturbed = ["G", "B", "C", "F"];
var sort = list.reduce((acc, cur) => {
acc[cur.name] = cur.distance;
return acc;
}, {});
disturbed.sort((a, b) => sort[a] - sort[b]);
console.log(disturbed)
You can use the sort method to do that
var list = [
{ name: "A", distance: 1},
{ name: "B", distance: 2},
{ name: "C", distance: 3},
{ name: "D", distance: 4},
{ name: "E", distance: 5},
{ name: "F", distance: 6},
{ name: "G", distance: 7},
{ name: "H", distance: 8}
];
var disturbed = ["G", "B", "C", "F"];
disturbed.sort((a, b) => {
var itemA = list.find(item => item.name === a);
var itemB = list.find(item => item.name === b);
return itemA.distance - itemB.distance;
});
disturbed.forEach(function(item) {
document.writeln(item[i])
})
You can use .find() to find the object with the specified name property that matches your elements in distributed. Once you have got this you can then get the distance property and calculate the difference to sort accordingly:
const list = [
{ name: "A", distance: 1},
{ name: "B", distance: 2},
{ name: "C", distance: 3},
{ name: "D", distance: 4},
{ name: "E", distance: 5},
{ name: "F", distance: 6},
{ name: "G", distance: 7},
{ name: "H", distance: 8}
];
const disturbed = ["G", "B", "C", "F"];
const res = disturbed.sort((a, b) => {
const {distance: d_a} = list.find(({name}) => name === a);
const {distance: d_b} = list.find(({name}) => name === b);
return d_a - d_b;
});
console.log(res);
A more efficient approach would be to create a new Map using .map() and then use .sort() on the keys form the map:
const list = [
{ name: "A", distance: 1},
{ name: "B", distance: 2},
{ name: "C", distance: 3},
{ name: "D", distance: 4},
{ name: "E", distance: 5},
{ name: "F", distance: 6},
{ name: "G", distance: 7},
{ name: "H", distance: 8}
];
const disturbed = ["G", "B", "C", "F"];
const lut = new Map(list.map(({name, distance}) => [name, distance]));
const res = disturbed.sort((a, b) => lut.get(a) - lut.get(b));
console.log(res);
This question already has answers here:
How to get the difference between two arrays of objects in JavaScript
(22 answers)
Closed 3 years ago.
Is there a way with lodash, where in result I do not have an object that satisfies a particular condition. For example,
o1 = [
{name: "a", id: 2, key: 33},
..,
]
o2 = [
{name: "ab", id: 2, key: 133}
]
Is there a way with lodash where the resultant array only includes the object that does not have the ids already present in o2. For example, resultant object after comparing o1 and o2 must not have the object from o2 because id=2 already exists in o1.
You can use _.differenceBy() and use the id of the point of reference:
const o1 = [{id: 1, name: 'a'},{id: 2, name: 'b'},{id: 3, name: 'c'}]
const o2 = [{id: 1, name: 'b'}]
const result = _.differenceBy(o1, o2, 'id')
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Maybe _.differenceWith?
const o1 = [
{id: 1, name: "a"},
{id: 2, name: "b"},
{id: 3, name: "c"},
]
const o2 = [
{id: 1, name: "b"},
]
const diffed = _.differenceWith(o1, o2, (o1, o2) => o1.id === o2.id)
console.log(diffed)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
You could do this without lodash by using .filter() and creating a Set. Firstly, you can create a set of all the ids in o2. Then, you can filter out any objects from o1 which have an id within the set. By using a set with .has() we are able to make our algorithm more efficient (than say using .includes() on an array).
See example below:
const o1 = [
{name: "a", id: 2, key: 33},
{name: "b", id: 3, key: 34},
{name: "c", id: 4, key: 34}
]
const o2 = [
{name: "d", id: 2, key: 134}
]
const o2_ids = new Set(o2.map(({id}) => id));
const result = o1.filter(({id}) => !o2_ids.has(id));
console.log(result); // includes objects with id's that appear in o1 but not in o2
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script>
var o1 = [
{name: "a", id: 77, key: 55},
{name: "a", id: 2, key: 33},
{name: "a", id: 1, key: 55}
]
var o2 = [
{name: "ab", id: 88, key: 133},
{name: "ab", id: 2, key: 133},
{name: "ab", id: 99, key: 133}
]
//sort first
o1.sort((a, b) => {
return a.id-b.id;//sort by id
});
o2.sort((a, b) => {
return a.id-b.id;//sort by id
});
//then compare one by one
function SearchX(OO1,OO2){
var o1_compare_place=0;
var o2_compare_place=0;
while(OO2.length>o2_compare_place && OO1.length>o1_compare_place ){
if(OO2[o2_compare_place].id<OO1[o1_compare_place].id){
o2_compare_place+=1;
}else if(OO2[o2_compare_place].id>OO1[o1_compare_place].id){
o1_compare_place+=1;
}else{
return "Exist Same!";
}
}
return "Different!";
}
document.body.innerHTML = SearchX(o1,o2)
</script>
</body>
</html>
Here you are
How can i filter this array base on same 'a', and max 'value' in 'a'
data = [
{a: 1, value: 12}, {a: 11, value: 39}, {a: 11, value: 150},
{a: 2, value: 15}, {a: 22, value: 83}, {a: 222, value: 12},
{a: 3, value: 55}, {a: 33, value: 9}, {a: 33, value: 1}
]
to become
data = [
{a: 1, value: 12}, {a: 11, value: 150},
{a: 2, value: 15}, {a: 22, value: 83}, {a: 222, value: 12},
{a: 3, value: 55}, {a: 33, value: 9},
]
i have planty of nasted object array, i cant filter it, same id with diferent value i just want to show the higest on it
You could store the index of the result set in a hash table and check if the actual value is greater, then take the actual object as result.
var data = [{ a: 1, value: 12 }, { a: 11, value: 39 }, { a: 11, value: 150 }, { a: 2, value: 15 }, { a: 22, value: 83 }, { a: 222, value: 12 }, { a: 3, value: 55 }, { a: 33, value: 9 }, { a: 33, value: 1 }],
hash = Object.create(null),
result = [];
data.forEach(function (o) {
if (!(o.a in hash)) {
hash[o.a] = result.push(o) - 1;
return;
}
if (result[hash[o.a]].value < o.value) {
result[hash[o.a]] = o;
}
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I have a multiplayer game and the gameplay data is stored like this:
var gameplays = [
{id: "1", player1: "bob", player2: "tim", score1: 2, score2: 14},
{id: "2", player1: "bob", player2: "tim", score1: 7, score2: 3},
{id: "3", player1: "bob", player2: "tim", score1: 6, score2: 10},
{id: "4", player1: "bob", player2: "tim", score1: 5, score2: 1}
];
What is the most efficient way to find the top 5 highscores from all the games by searching "score1" and "score2" and output them like this:
HIGHSCORES
1. Tim - 14
2. Tim - 10
3. Bob - 7
4. Bob - 6
5. Bob - 5
var scores = [];
for (var i = 0; i < gameplays.length; i++) {
scores.push({score: gameplays[i].score1, name: gameplays[i].player1});
scores.push({score: gameplays[i].score2, name: gameplays[i].player2});
}
scores.sort(function (a, b) {
return b.score - a.score;
});
scores.splice(0, 5);
First, get the scores and flatten them in a scores array along with score and name of individual.
Then, we sort the array and splicing will get the top 5 scores with name.
const gameplays = [
{id: "1", player1: "bob", player2: "tim", score1: 2, score2: 14},
{id: "2", player1: "bob", player2: "tim", score1: 7, score2: 3},
{id: "3", player1: "bob", player2: "tim", score1: 6, score2: 10},
{id: "4", player1: "bob", player2: "tim", score1: 5, score2: 1}
];
First, write all relevant game information into an array of objects, each of which contain a player key corresponding to the player's name and a score key, which corresponds to the score:
const results = [];
gameplays.forEach(game => {
for(let i = 1; i <= 2; i++) {
results.push({});
results[results.length - 1].player = `${game[`player${i}`].slice(0, 1).toUpperCase()}${game[`player${i}`].slice(1).toLowerCase()}`;
results[results.length - 1].score = game[`score${i}`];
}
});
Then, sort the array in descending order of scores before only keeping the top 5 with slice.
const topFive = results.sort((result1, result2) => result2.score - result1.score)
.slice(0, 5);
Finally, display the top 5 scores.
console.log('High Scores');
for(let i = 0; i < topFive.length; i++) {
console.log(`${i + 1}. ${topFive[i].player} - ${topFive[i].score}`);
}
You can do it in a sort pretty easily I think with:
gameplays.sort(function(_a, _b){
var a = _a.score1 > _a.score2 ? _a.score1 : _a.score2;
var b = _b.score1 > _b.score2 ? _b.score1 : _b.score2;
if(a < b) {
return 1;
}
if(a > b) {
return -1;
}
return 0;
})
Then, you you can access the top five with:
gameplays.slice(0, 5)
If you'r going to benchmark this I would be interested in the performance of the "functional" kind of solution with Ramda.
var gameplays = [
{id: "1", player1: "bob", player2: "tim", score1: 2, score2: 14},
{id: "2", player1: "bob", player2: "tim", score1: 7, score2: 3},
{id: "3", player1: "bob", player2: "tim", score1: 6, score2: 10},
{id: "4", player1: "bob", player2: "tim", score1: 5, score2: 1}
];
// find the 5 top highscores regardless which player
const normalizeScore = ({id, player1, score1, player2, score2}) =>
[{id, player1, score: score1}, {id, player2, score: score2}];
const sortByScore = (play1, play2) => play2.score - play1.score;
const normalizeGameplays = R.chain(normalizeScore); // chain === flatMap
const sortGameplays = R.sort(sortByScore);
const topFive = R.slice(0, 5);
const highscore = R.compose(topFive, sortGameplays, normalizeGameplays);
console.log(highscore(gameplays));
#See: https://jsbin.com/wixowu/edit?html,js,console