简体   繁体   中英

Filtering an array of Objects in javascript

I'm really new to JS, and I'm now stuck on a task, hope someone can guide me through it.

I have an Array of Objects, like this one:

var labels = [
            // labels for pag 1
            {pageID:1, labels: [
                {labelID:0, content:[{lang:'eng', text:'Txt1 Eng'}, {lang:'de', text:'Txt1 De:'}]},
                {labelID:1, content:[{lang:'eng', text:'Txt 2 Eng:'}, {lang:'de', text:'Txt2 De:'}]},
                {labelID:2, content:[{lang:'eng', text:'Txt 3 Eng:'},{lang:'de', text:'Txt 3 De:'}]}
            ]},

            // labels for pag 2
            {pageID:2, labels: [
                {labelID:0, content:[{lang:'eng', text:'Txt1 Eng'}, {lang:'de', text:'Txt1 De:'}]},
                {labelID:1, content:[{lang:'eng', text:'Txt 2 Eng:'}, {lang:'de', text:'Txt2 De:'}]},
                {labelID:2, content:[{lang:'eng', text:'Txt 3 Eng:'},{lang:'de', text:'Txt 3 De:'}]}
            ]}
    ]

What I am trying to do is write a function to return me an array of labels (Objects) for a specific page and a specific lang. By calling this function specifying pageID 1 and lang eng, I'm basically trying to build an array like this one:

var desideredArray = [
    {labelID:0, text:'Txt1 Eng'}, 
    {labelID:1, text:'Txt1 Eng'}, 
    {labelID:2, text:'Txt2 Eng'}
] 

Now, I'm trying to write the function to retrieve/build the new array:

this.getLabelsForPageAndLang = function (numPage, lang) {
            // this part filters the main object and selects the object with pageID == numPage
        var result = labels.filter(function( obj ) {
            return obj.pageID == numPage;
        });

        var tempResult = result[0].labels;
        var desiredResults = [];  // here I want to store the new objects
        for (var i=0; i<tempResult.length; i++) {
            var simpleLabelObject = {};
            simpleLabelObject.labelID = tempResult[i].labelID;
            // simpleLabelObject.text = ?????

            results[i] = simpleLabelObject;
        }

        console.log (results);

    };

...but how can I access the right value (the one corresponding the lang selected) in the content property?

You can use the same technique as the one used to keep the matching page: the filter method.

this.getLabelsForPageAndLang = function (numPage, lang) {
        // this part filters the main object and selects the object with pageID == numPage
    var result = labels.filter(function( obj ) {
        return obj.pageID == numPage;
    });
    var contentFilter = function(obj){ return obj.lang === lang};

    var tempResult = result[0].labels;
    var desiredResults = [];  // here I want to store the new objects
    for (var i=0; i<tempResult.length; i++) {
        var simpleLabelObject = {};
        simpleLabelObject.labelID = tempResult[i].labelID;
        var matching = tempResult[i].content.filter(contentFilter);
        simpleLabelObject.text = matching[0].text;

        desiredResults[i] = simpleLabelObject;
    }

    console.log (desiredResults);

};

I didn't do bound checks because in your code you assumed there is always a matching element, but it would probably be wise to do it.

And if you want to avoid creating two closures each time the function is called, you can prototype an object for that:

var Filter = function(numPage, lang) {
    this.numPage = numPage;
    this.lang = lang;
};

Filter.prototype.filterPage = function(obj) {
    return obj.pageID === this.numPage;
}

Filter.prototype.filterLang = function(obj) {
    return obj.lang === this.lang;
}

Filter.prototype.filterLabels = function(labels) {
    var result = labels.filter(this.filterPage, this);

    var tempResult = result[0].labels;
    var desiredResults = [];  // here I want to store the new objects
    for (var i=0; i<tempResult.length; i++) {
        var simpleLabelObject = {};
        simpleLabelObject.labelID = tempResult[i].labelID;
        var matching = tempResult[i].content.filter(this.filterLang, this);
        simpleLabelObject.text = matching[0].text;

        desiredResults[i] = simpleLabelObject;
    }

    return desiredResults;
}

console.log(new Filter(1, "eng").filterLabels(labels));

Just filter again:

var getLabelsForPageAndLang = function (numPage, lang) {
    // this part filters the main object and selects the object with pageID == numPage
    var result = labels.filter(function (obj) {
        return obj.pageID == numPage;
    }); 
    var tempResult = result[0].labels;
    var desiredResults = []; // here I want to store the new objects
    for (var i = 0; i < tempResult.length; i++) {
        var simpleLabelObject = {};
        simpleLabelObject.labelID = tempResult[i].labelID;
        var lg = tempResult[i].content.filter(function (lg) {
            return lg.lang == lang;
        });
        simpleLabelObject.text = lg[0].text;

        desiredResults.push(simpleLabelObject);
    }

    console.log(desiredResults);

};

http://jsfiddle.net/9q5zF/

A rather 'safe' implementation for cases when pages have the same pageID and multiple contents with the same lang :

this.getLabelsForPageAndLang = function(numPage, lang) {
    var result = [];
    var pages = labels.filter(function( obj ) {
        return obj.pageID === numPage;
    });
    for (var p = pages.length - 1; p >= 0; p--) {
        var page = pages[p];
        for(var i = page.labels.length - 1; i >= 0; i--) {
            var labelId = page.labels[i].labelID;
            for (var j = page.labels[i].content.length - 1; j >= 0; j--){
                if (page.labels[i].content[j].lang === lang) {
                    result.push({labelID: labelId, test: page.labels[i].content[j].text});
                }
            }
        }
    }    
    console.log(result);
}

Fiddle: http://jsfiddle.net/6VQUm/

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