简体   繁体   中英

Create multi-dimensional array index in Javascript?

I have a ajax request that is returning to me an object that looks roughly like the following:

[
 {category: "Test Category", id: "1", name: "Test",  language: "English"},
 {category: "Test Category", id: "2", name: "Test2", language: "English"},
 {category: "A test",        id: "3", name: "Test3", language: "Spanish"},
 {category: "Test Category", id: "4", name: "Test4", language: "Spanish"}
]

Basically I need a way to do the following:

  • List all categories that exist in ONLY English or Spanish
  • List all ID's that exist in a specified language
  • List all ID's that exist in a specified category

Now I'm fairly sure the best route to do this is to create my own temp arrays that can house that data but I'm not confident enough in Javascript to write the correct loop to get that data. I know in PHP I'd do something like $category['Test Category'][] = 3 while looping.

The idea is I need the ability to filter things based on the user selecting to filter by English and then by a category within that.

Can someone point me in the right direction?

Some ways to use underscore for your tasks: http://underscorejs.org

var data = [
 {category: "Test Category", id: "1", name: "Test",  language: "English"},
 {category: "Test Category", id: "2", name: "Test2", language: "English"},
 {category: "A test",        id: "3", name: "Test3", language: "Spanish"},
 {category: "Test Category", id: "4", name: "Test4", language: "Spanish"}
]

// Filter by spanish
var output = _.where(data, {"language":"Spanish"});

// Filter by category
var output = _.where(data, {"category":"A test"});

// List specific category ids
var output = _.pluck(_.where(data, {"category":"A test"}), "id");

// List category names
var output = _.pluck(_.where(data, {"language":"English"}), "category");

// Group by languages
var output = _.groupBy(data, function(value) { 
  return value.language
});
output["English"];

Since you included jQuery in the tag I thought I would use it:

//All categories with English or spanish language (categories is the array)
$.grep(categories, function(c) { return c.language=='English' || c.language == 'Spanish'; });

Using vanilla JS, where json is your original array, you could use:

function filterJson(attr, obj) {
    var attrList = [],
        match,
        tempAttr,
        i;

    for (i = 0; i < json.length; i += 1) {
        match = true;

        for (tempAttr in obj) {
            if (!obj[tempAttr].test(json[i][tempAttr])) {
                match = false;
                break;
            }
        }

        if (match) attrList.push(json[i][attr]);
    }

    return attrList;
}

And use it like this:

"List all categories that exist in ONLY English or Spanish"

filterJson('category', {
    language: /(English|Spanish)/
});
// => ["Test Category", "Test Category", "A test", "Test Category"] 

"List all ID's that exist in a specified language"

filterJson('id', {
    language: /English/
});
// => ["1", "2"] 

"List all ID's that exist in a specified category"

filterJson('id', {
    category: /Test Category/
});  
// => ["1", "2", "4"] 

If you can count on a few assumptions about the data always being true -- eg, that you'll only ever have category:, id:, name:, and language:, and that there will never be a colon or comma anywhere in the name or category -- then I would actually suggest sticking all the information into single strings and use RegExp to find it.

Eg:

[
 "category:Test Category, id:1, name:Test,  language:English",
 "category:Test Category, id:2, name:Test2, language:English",
 "category:A test,        id:3, name:Test3, language:Spanish",
 "category:Test Category, id:4, name:Test4, language:Spanish"
]

Now, to find a values for an entry, use RegExp.match().

var m = /^category:([^,]+)\s+id:(\d+),\s+name:([^,]+),\s+language:(.+)$/i;
// m[1] = Test Category
// m[2] = 1;
// m[3] = Test2
// m[4] = Spanish

And you can search by using tests.

function my_filter(criteria) {
    var results = [];
    var re = new RegExp(criteria);
    for (var i=0; i<array.length; i++) {
        if (array[i].test(re))
            results.push(array[i]);
    }
    return results;
}
var english_array = my_filter('language:english');
var atest_array = my_filter('category:a test');

The magic Google terms are "map" and "reduce".

var data = [...the JSON data parsed with JSON.parse() if necessary...]

var categoriesInEnglish = data.reduce(function(accumulator, category) {
    if(category.language = 'English') {
        accumulator.push(category.id);
    }
});

see http://www.mrspeaker.net/2011/05/02/conventional-interfaces/ and http://www.mrspeaker.net/2011/04/27/reducing-map/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM