2

I need to get a new object countriesFiltered , filtering just countries with population under a billion. I'm using in the map part: return { key : countries[key]}. I think is not correct, how i can build a new object ? i must use push or something like that?

var countries = {
    China: 1371980000,
    India: 1276860000,
    'United States': 321786000,
    Indonesia: 255461700,
    Brazil: 204873000,
    Pakistan: 190860000
};
var countriesFiltered = Object.keys(countries).filter(function(key) {
    return countries[key] <= 1000000000;
}).map(function(key) {
    return { key : countries[key]};
});
console.log(countriesFiltered);
t3dodson
  • 3,949
  • 2
  • 29
  • 40
stackdave
  • 6,655
  • 9
  • 37
  • 56
  • hmm, I'm getting an object with the filtered countries after running your code. What are you trying to do? – Guillermo Aug 12 '16 at 04:05
  • I need like result; var countriesFiltered = { United States': 321786000, Indonesia: 255461700, Brazil: 204873000, Pakistan: 190860000 }; – stackdave Aug 12 '16 at 04:09
  • Added an answer and a fiddle. https://jsfiddle.net/swaprks/aewf0erx/ – Swaprks Aug 12 '16 at 04:30

5 Answers5

3

Close! Just use Array.reduce instead of Array.map. Object property names can't be computed unless you are using ES2015. So you need to use reduce to construct a new object and then assign each property individually.

var countries = {
  China: 1371980000,
  India: 1276860000,
  'United States': 321786000,
  Indonesia: 255461700,
  Brazil: 204873000,
  Pakistan: 190860000
};
var countriesFiltered = Object.keys(countries).filter(function(key) {
  return countries[key] <= 1000000000;
}).reduce(function(obj, key) {
  // Assign key/val to new object
  obj[key] = countries[key];
  
  return obj;
}, {});

document.write('<pre>' + JSON.stringify(countriesFiltered, null, 2) + '</pre>');

EDIT: Using ES2015 computed name properties would look something like the following. Note this will only work in supported browsers.

var countries = {
  China: 1371980000,
  India: 1276860000,
  'United States': 321786000,
  Indonesia: 255461700,
  Brazil: 204873000,
  Pakistan: 190860000
};
var countriesFiltered = Object.keys(countries).filter(function(key) {
  return countries[key] <= 1000000000;
}).reduce(function(obj, key) {
  // Create object with computed property name
  // and assign to obj
  return Object.assign(obj, {
    [key]: countries[key]
  });
}, {});

document.write('<pre>' + JSON.stringify(countriesFiltered, null, 2) + '</pre>');

Bonus: for fun you could use the replacer function to leverage the power of JSON.stringify to filter the object. While it does show there are a lot of different approaches to solving this I wouldn't recommend this approach.

var countries = {
  China: 1371980000,
  India: 1276860000,
  'United States': 321786000,
  Indonesia: 255461700,
  Brazil: 204873000,
  Pakistan: 190860000
};
var countriesFiltered = JSON.parse(JSON.stringify(countries, filterCountries));

function filterCountries(key, val) {
  if (val > 1000000000) {
    return undefined;
  }

  return val;
}

document.write('<pre>' + JSON.stringify(countriesFiltered, null, 2) + '</pre>');
Jason Cust
  • 10,743
  • 2
  • 33
  • 45
  • please; can you give me a solution with ES2015 too ? thanks – stackdave Aug 12 '16 at 04:52
  • @stackdave I updated the answer with a computed name property approach as well as a little fun example to maybe broaden your exposure to JavaScript. Enjoy! – Jason Cust Aug 12 '16 at 12:13
0

Try using the following function:

Object.filter = (obj, predicate) => 
    Object.keys(obj)
          .filter(key => predicate(obj[key]))
          .reduce((res, key) => (res[key] = obj[key], res), {});


var filtered = Object.filter(countries, countrie => countrie <= 1000000000); 
console.log(filtered);

This should do it for you!

Reference: JavaScript: filter() for Objects

Community
  • 1
  • 1
James111
  • 15,378
  • 15
  • 78
  • 121
  • I wouldn't recommend modifying the native `Object` for a [variety of reasons](https://www.nczonline.net/blog/2010/03/02/maintainable-javascript-dont-modify-objects-you-down-own/). – Jason Cust Aug 12 '16 at 04:14
  • origina example; just does: return countries[key] <= 1000000000; instead return { key : countries[key]}; in my example... i've thought i needed to change just one line, but I see it's not a simple thing to get an row from the object .... and do a sort of push... i'm studying your solution is very complex for me, but i ll study and i will reply it, – stackdave Aug 12 '16 at 04:16
  • @JasonCust I did not understand very well; the solution is not good then? with Object.filter, is modifying the native object? – stackdave Aug 12 '16 at 04:21
  • @JasonCust - This doesn't affect the filter method itself. It doesn't break any of the current functionality. – James111 Aug 12 '16 at 04:22
0

I am not 100% sure what you are looking for but if you are looking for a new object with each country name as the property and the population you can try.

var countries = {
  China: 1371980000,
  India: 1276860000,
  'United States': 321786000,
  Indonesia: 255461700,
  Brazil: 204873000,
  Pakistan: 190860000
};
var countriesFiltered = {};
Object.keys(countries).filter(function(key) {
  return countries[key] <= 1000000000;
}).map(function(key) {
  countriesFiltered[key] = countries[key];
});
console.log(countriesFiltered);

This results in:

{
    United States: 321786000, 
    Indonesia: 255461700, 
    Brazil: 204873000, 
    Pakistan: 190860000
}

If you want an array of Key Value Pairs you could try.

var countries = {
  China: 1371980000,
  India: 1276860000,
  'United States': 321786000,
  Indonesia: 255461700,
  Brazil: 204873000,
  Pakistan: 190860000
};
var countriesFiltered = Object.keys(countries).filter(function(key) {
  return countries[key] <= 1000000000;
}).map(function(key) {
    return { country: key, population: countries[key]}; 
});
console.log(countriesFiltered);

EDIT: Answer to comment

what does mean exactly, reausable, where i can read about that ?

If you review @answer-38909742 you will see that they have modified the Object type and added a static method Object.filter() with the signature of Object.filter = (obj, predicate) => {}

This then makes it reusable and not limited to the scope of the function but to any object.

If this was placed in a global script somewhere in your application you can then resuse this method on any object in any scope.

As stated in his question simply by calling.

Object.filter(countries, countrie => countrie <= 1000000000); 
Community
  • 1
  • 1
Nico
  • 12,493
  • 5
  • 42
  • 62
  • This does do it, but it wouldn't really be re-usable as it's pretty much hard coded to use the countries object – James111 Aug 12 '16 at 04:11
  • i was looking for a solution without use: var countriesFiltered = {}; i need an objet , not an array, i m studying anyway yours solution, thanks – stackdave Aug 12 '16 at 04:13
  • @stackdave if you run the first solution it will return an object, the second solution returns an array. – Nico Aug 12 '16 at 04:14
  • @James111 agreed it is not reusable. However didnt specify that in the OP. :) – Nico Aug 12 '16 at 04:14
  • what does mean exactly, reausable, where i can read about that ? – stackdave Aug 12 '16 at 04:17
  • Updated answer to asnwer your last comment – Nico Aug 12 '16 at 04:24
  • When you program it's best to make re-usable code when you can @stackdave Meaning you can use a function anywhere! In this case you've built a function that has a lot of logic that can only be applied to the countries object. There are ways to make it so the function can be used on other objects (e.g a scores object) – James111 Aug 12 '16 at 05:06
0

Object has only unique keys. So if your countries are going to be unique then you can use the following code:

    var countries = {
      China: 1371980000,
      India: 1276860000,
      'United States': 321786000,
      Indonesia: 255461700,
      Brazil: 204873000,
      Pakistan: 190860000
    };
var countriesFiltered = {};

for ( var country in countries ) {
   if ( countries[country] <= 1000000000 ) {
      countriesFiltered[country] = countries[country];
   }
}

console.log(countriesFiltered);
Swaprks
  • 1,553
  • 11
  • 16
-2

Well I will try to understand your problem instead of giving you a different solution. Actually if you want to assign a variable as a key in a javascript object there is a different way for that. eg.

var obj = {};
var key = 'abc';
obj[key] =  123;

You wont be able to assign a variable as a key directly to an object.

var key = 'abc';
var obj = {key : 123}

It would result in an error.

Here is your answer

 var countries = {
    China: 1371980000,
    India: 1276860000,
    'United States': 321786000,
    Indonesia: 255461700,
    Brazil: 204873000,
    Pakistan: 190860000
};
var countriesFiltered = Object.keys(countries).filter(function(key) {
    return countries[key] <= 1000000000;
}).map(function(key) {
    var obj = {};
    obj[key] = countries[key];
    return obj;
}).reduce(function(prevKey, currentKey) {
    return Object.assign(prevKey , currentKey);
})
    console.log(countriesFiltered);

Follow this good post already posted for the same. JavaScript set object key by variable

Community
  • 1
  • 1
ajaykumar
  • 646
  • 7
  • 17
  • This doesn't actually provide a solution for the OP – James111 Aug 12 '16 at 04:21
  • Pls explain how this couldn't answer James – ajaykumar Aug 12 '16 at 04:25
  • Your example returns an object array – Nico Aug 12 '16 at 04:26
  • 1
    You've since change your answer after my initial comment, it still doesn't do what the OP wants. Instead this is returning an Array of objects, not an object with key + values. – James111 Aug 12 '16 at 04:26
  • Apologies !!! My Bad!! I just added the reduce after map now. In the post StackDave was wrongly interpreted the variable key assignment to an object. just wanted to clear that though.. I guess already it is answered.. Thanks for pointing it out James!! One vote for your comment! – ajaykumar Aug 12 '16 at 04:43