2

I have an array of objects and need to create a new array which contains the values of a specific key within the objects. Is there a more elegant way than the following code (note: without using anything more than JQuery). Expected result is: 455, 387, 495

var arr=[{sid:387,rank:2},{sid:455,rank:1},{sid:364,rank:4},{sid:495,rank:3}];
var topThreeTemp = arr.filter(function(a){return a.rank<4;}).sort(function(a,b){return a.rank>b.rank;});
var topThreeSIDs=[];
for(var i=0;i<topThreeTemp.length;i++){
    topThreeSIDs.push(topThreeTemp[i].sid);
}
console.log(topThreeSIDs.join(", "));
2
  • 1
    topThreeSIDs = topThreeTemp.map(t => t.sid) Commented Aug 24, 2018 at 10:03
  • 1
    Array.map() so something like topThreeTemp.map(function( item ) { return item.sid; }); Commented Aug 24, 2018 at 10:04

5 Answers 5

4

Use ES6 map, instead of for and ES6 arrow functions (syntax sugars):

const arr = [
 { sid: 387,rank: 2 },
 { sid: 455,rank: 1 },
 { sid: 364,rank: 4 },
 { sid: 495,rank: 3 }
]

const topThreeSIDs = arr
  .filter(({ rank }) => rank < 4)
  .sort((a, b) => a.rank > b.rank)
  .map(({ sid }) => sid)
  

console.log(topThreeSIDs.join(', '))

Sign up to request clarification or add additional context in comments.

Comments

2

You could filter, sort with delta, slice and map sid as result array.

var array = [{ sid: 387, rank: 2 }, { sid: 455, rank: 1 }, { sid: 364, rank: 4 }, { sid: 495, rank: 3 }],
    top3 = array
        .filter(({ rank }) => rank < 4)
        .sort((a, b) => a.rank - b.rank)
        .slice(0, 3)
        .map(({ sid }) => sid);

console.log(top3.join(", "));

4 Comments

Apparently there's no need for the slice, as it seems ranks are unique and they're already taking the ones smaller than 4
@FedericoklezCulloca, actually right, but if you have more data, you need to slice for top 3.
@NinaScholz - As you are filtering on based on rank ( < 4), and rank being unique, there will never be case when there will be more than 3 records left after filter. I think this is what Federico meant.
@NinaScholz : Yes, this is useful since the implicit assumption that ranks are unique is not necessarily true. Thanks.
1

Use Array.map

var arr=[{sid:387,rank:2},{sid:455,rank:1},{sid:364,rank:4},{sid:495,rank:3}];

var result = arr.filter(({rank}) => rank < 4).sort((a,b) => a.rank > b.rank).map(({sid}) => sid);
console.log(result.join(", "));

Comments

0
function pluck(objs, name, condition) {
        var sol = [];
        for (var i in objs) {
            if (objs[i].hasOwnProperty(name) && condition && condition(objs[i])) {
                // console.log(objs[i][name]);
                sol.push(objs[i][name]);
            }
        }
        return sol;
    }

    var arr = [{sid: 387, rank: 2}, {sid: 455, rank: 1}, {sid: 364, rank: 4}, {sid: 495, rank: 3}];
    var pluckedArray = pluck(arr, sid, function (item) {
        return item.rand < 4; // your custom condition
    })

Comments

0

How about iterate the array only once, and build the resultant array?

arr.reduce((r, {rank, sid})=>(rank < 4 && (r[rank -1] = sid), r), [])

var arr = [{ sid: 387, rank: 2 }, { sid: 455, rank: 1 }, { sid: 364, rank: 4 }, { sid: 495, rank: 3 }],
    top3 = arr.reduce((r, {rank, sid})=>(rank < 4 && (r[rank -1] = sid), r), []);
    
console.log(top3);

Note: When you need top 3 within highest rank 4 and also know ranks are unique, you can use this. If ranks are not unique you can use r.splice(rank-1, 0, sid) instead of r[rank-1] = sid and slice top 3 at the end.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.