filtering JSON using underscore

2019-08-02 08:16发布

问题:

I got a JSON name collection like this:

[{

   "name":"Jim",
   "prize":"Nokia Mobile"
  },
  {

   "name":"Marry",
   "prize":"iPhone"
  },
  {

   "name":"Alice",
   "prize":"iPad"
  }

]

now I'd like to filter this JSON by a string: var data= "m";

so, this is what I've done:

    var data= "m";

    collection = _.filter(collection,function(c){


        return _.any(c,function(k){


            return k.name.toLowerCase().indexOf(data.toLowerCase()) != -1;

        });


    });

so, in this case, collection return elements which has m in their name.

However, I've got "Cannot call method 'toLowerCase' of undefined".

I tried to put an alert "alert(c.name);" before the last return, and it's return "undefined". It shouldn't be, isn't it?

what need I change to fix this?

回答1:

See this http://underscorejs.org/#filter

Try this:

var data= "m";

collection = _.filter(collection,function(myObject){
    return myObject.name.toLowerCase().indexOf(data.toLowerCase()) != -1;
});

Hope it helps.



回答2:

EDIT: Seems like your core problem here is misunderstanding of the input and output of the underscore functions any and filter. I realised after writing my answer I'm not really even sure what your code should be doing - but reading the docs for filter and any, along with the points below and in the rest of the answers, will surely help you solve your problem in the right way.


You shouldn't use _.any here - that tells you if any element in an array passes a test (implemented as a function which you pass to it). You shouldn't use _.any at all here, if you need to test name, just test name directly on the object.

_.filter is all you want - this returns a new array containing all elements from the passed in array which pass the test (likewise, implemented in the function you pass). In this case, all the objects where the name string contains the data string. See the code below for clarity on how each element from collection is passed and used inside the test function passed to _.filter.

Another point - if you can't guarantee the integrity of the data coming into collection, to avoid errors you should check first if the name property is defined - if it's not, fail the test.

var collection = [
   {
      "name":"Jim",
      "prize":"Nokia Mobile"
   },
   {
      "name":"Marry",
      "prize":"iPhone"
   },
   {
      "name":"Alice",
      "prize":"iPad"
   }];

var data = 'm';

collection = _.filter(collection,function(element){
    return element.name && element.name.toLowerCase().indexOf(data.toLowerCase()) != -1;
});

Also, you don't need to lowercase data here - you know it's lowercase - unless that data = 'm' declaration is just a placeholder for some other, unpredictable, input :-)



回答3:

You have made it too complicated, simply:

var data = [{
   "name":"Jim",
   "prize":"Nokia Mobile"
  },
  {

   "name":"Marry",
   "prize":"iPhone"
  },
  {

   "name":"Alice",
   "prize":"iPad"
  }
];

var fiterTerm = "m";

var collection = _.filter(data, function(item){
    return item.name.toLowerCase().indexOf(fiterTerm.toLowerCase()) != -1;
});

console.log(collection);


回答4:

You need to put quotes round your values. And then: _any function with an object as collection passes 2 parameters to the callback function rather than one.

_.any({ name:"Jim", price: "Phone" },function(value,key) {
  alert(value+" "+key)
}); 

Will give you alerts with "Jim name" and then "Phone price". so you do not have to use the .name property on the value parameter.



回答5:

True your JSON in the example isn't valid, the strings do need quotes as meager pointed out.

If it where valid and you wanted to filter the array using underscore I would use something like this

http://underscorejs.org/#filter

var data = 'm';
var filteredcollection = _.filter(collection, function(item){ 
    return item.name.toLowerCase().indexOf(data) != -1; 
});

Hope this helps