最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Javascript filter an associative array with another array - Stack Overflow

programmeradmin2浏览0评论

How to filter an associative array with another one?

function filter (a,f) {
    console.log (a) ;
    console.log (f) ;  

    //Using f as filter, How to get only these rows fom a ?
    //{"XD_A":"XDR","XD_B_1":"38","XD_B_2":"PB"},
    //{"XD_A":"XDR","XD_B_1":"38","XD_B_2":"PB"},                
}

function test() {
    var data = [{"XD_A":"XDL","XD_B_1":"38","XD_B_2":"PB"},
    {"XD_A":"XDR","XD_B_1":"51","XD_B_2":"PB"},
    {"XD_A":"XDL","XD_B_1":"58","XD_B_2":"PB"},
    {"XD_A":"XDR","XD_B_1":"38","XD_B_2":"PB"},
    {"XD_A":"XDL","XD_B_1":"76","XD_B_2":"PB"},
    {"XD_A":"XDR","XD_B_1":"38","XD_B_2":"PB"}] ;
    var filters =[{"XD_A":"XDR"},{"XD_B_1":"38"}] ;
    filter (data,filters) ;
}

Thanks in advance,

best regards

Massimo

How to filter an associative array with another one?

function filter (a,f) {
    console.log (a) ;
    console.log (f) ;  

    //Using f as filter, How to get only these rows fom a ?
    //{"XD_A":"XDR","XD_B_1":"38","XD_B_2":"PB"},
    //{"XD_A":"XDR","XD_B_1":"38","XD_B_2":"PB"},                
}

function test() {
    var data = [{"XD_A":"XDL","XD_B_1":"38","XD_B_2":"PB"},
    {"XD_A":"XDR","XD_B_1":"51","XD_B_2":"PB"},
    {"XD_A":"XDL","XD_B_1":"58","XD_B_2":"PB"},
    {"XD_A":"XDR","XD_B_1":"38","XD_B_2":"PB"},
    {"XD_A":"XDL","XD_B_1":"76","XD_B_2":"PB"},
    {"XD_A":"XDR","XD_B_1":"38","XD_B_2":"PB"}] ;
    var filters =[{"XD_A":"XDR"},{"XD_B_1":"38"}] ;
    filter (data,filters) ;
}

Thanks in advance,

best regards

Massimo

Share Improve this question edited Dec 5, 2016 at 6:31 CompSciFly 1703 silver badges19 bronze badges asked Dec 5, 2016 at 6:20 user7250540user7250540 2
  • 1 show us something you have tried? – kukkuz Commented Dec 5, 2016 at 6:21
  • var rf = _.dropRightWhile(data, filters) ; but without success. Filters will change and "increase" dynamically – user7250540 Commented Dec 5, 2016 at 6:32
Add a ment  | 

3 Answers 3

Reset to default 2

let data = [{"XD_A":"XDL","XD_B_1":"38","XD_B_2":"PB"},
{"XD_A":"XDR","XD_B_1":"51","XD_B_2":"PB"},
{"XD_A":"XDL","XD_B_1":"58","XD_B_2":"PB"},
{"XD_A":"XDR","XD_B_1":"38","XD_B_2":"One"},
{"XD_A":"XDL","XD_B_1":"76","XD_B_2":"PB"},
{"XD_A":"XDR","XD_B_1":"38","XD_B_2":"Two"}],
    filters =[{"XD_A":"XDR"},{"XD_B_1":"38"}];

console.info(filter(data, filters));

function filter(d, f){
  return data.filter(e => {
    try{
      f.forEach(o => {
        Object.keys(o).forEach(key => {
          if(e[key] !== o[key]) throw new 1;
        });
      });
      
      return true;
    }catch(e){
      return false;
    }
  });
}

You could fiter the array without a try catch block.

function filter(data, filter) {
    return data.filter(function (d) {
        return filter.every(function (f) {
            var k = Object.keys(f)[0];
            return d[k] === f[k];
        });
    });
}


var data = [{ "XD_A": "XDL", "XD_B_1": "38", "XD_B_2": "PB" }, { "XD_A": "XDR", "XD_B_1": "51", "XD_B_2": "PB" }, { "XD_A": "XDL", "XD_B_1": "58", "XD_B_2": "PB" }, { "XD_A": "XDR", "XD_B_1": "38", "XD_B_2": "PB" }, { "XD_A": "XDL", "XD_B_1": "76", "XD_B_2": "PB" }, { "XD_A": "XDR", "XD_B_1": "38", "XD_B_2": "PB" }],
    filters = [{ "XD_A": "XDR" }, { "XD_B_1": "38" }];

console.log(filter(data, filters));
.as-console-wrapper { max-height: 100% !important; top: 0; }

ES6

function filter(data, filter) {
    return data.filter(d => filter.every(f => (k => d[k] === f[k])(Object.keys(f)[0])));
}


var data = [{ "XD_A": "XDL", "XD_B_1": "38", "XD_B_2": "PB" }, { "XD_A": "XDR", "XD_B_1": "51", "XD_B_2": "PB" }, { "XD_A": "XDL", "XD_B_1": "58", "XD_B_2": "PB" }, { "XD_A": "XDR", "XD_B_1": "38", "XD_B_2": "PB" }, { "XD_A": "XDL", "XD_B_1": "76", "XD_B_2": "PB" }, { "XD_A": "XDR", "XD_B_1": "38", "XD_B_2": "PB" }],
    filters = [{ "XD_A": "XDR" }, { "XD_B_1": "38" }];

console.log(filter(data, filters));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Associative array sorting, hmmm? I wanted to do this in a non-ES6 way (since I arrived at its solution in a few minutes; borrrrrring. JK I love you ES6!). I used your exact criteria from your own example.

Here's a non-library, non-ES6 way (just in case, just for fun) that includes some extra output results using the args: contains, results, strict.

It also scales when filters need to increase/decrease. Note: it does not filter with multiple object properties as criteria, but instead exactly as you have posted: using multiple array items that are "associative arrays" (but is possible to change this, obviously).

This is my first post on SO, after many years using it (sorry.) Anyway, hope it works for you (FIDDLE HERE) and others, Massimo!

PS - If it's crap/buggy I'll try to find time to help you fix it.

/**
* _filterStrict only gives back data if both filter criteria are satisfied
* @param data {obj}
*        filterList {arr}
* @returns bool
*/
var _filterStrict = function(data, filterList) {
  var filterLength = filterList.length
  // handy little truthy array
  var strictMatchResults = []
    for (var i = 0; i < filterLength; ++i) {
    for (var prop in filterList[i]) {
        // we need to match both the property and value
        if (data.hasOwnProperty(prop) && data[prop] === filterList[i][prop]) {
        strictMatchResults.push(true)
      } else {
        // no truthy for you! YOU CAN'T HANDLE THE TRUTH!
        continue;
      }
    }
  }
  return strictMatchResults.length === filterLength ? true : false
}

/**
* _filterContains loose check; if data is found to be matching, it's a match.
* @param prop {str}
*        val {str} // !could be extended to allow more types!
*        filterList {arr}
* @returns bool
*/
var _filterContains = function(prop, val, filterList) {
  var filterLength = filterList.length
  var found = []
    for (var i = 0; i < filterLength; ++i) {
    // we need to match both the property and value
    if (filterList[i].hasOwnProperty(prop) && filterList[i][prop] === val) {
        return true
    } else {
        // "W-w-what? I have to go back to the expression, again? Ugh."
        continue;
    }
  }
}

/**
* _filterChoose detects which filter to use via filterMode and selects
*   the appropriate internal filter
* @param dataToCheck {obj}
*        filterList {arr}
*        filterMode {str}
* @returns arr
*/
var _filterChoose = function(dataToCheck, filterList, filterMode) {
  var dataMatchesFilter = null
  var initObjFlag = false
  var filterLength = filterList.length

  // run in "strict search" mode
  if (filterMode === 'strict') {        
    return _filterStrict(dataToCheck, filterList) ? dataToCheck : null
  }

  // loop through slice of data
  for (var prop in dataToCheck) {
    var val = dataToCheck[prop]
    // check against filter criteria
    if (_filterContains(prop, val, filterList)) {
        // only create the object literal once
      if (initObjFlag === false) {
          initObjFlag = true
        dataMatchesFilter = {}
      }
      // only return the found results from the array
      if (filterMode === 'results') {
        dataMatchesFilter[prop] = val
      }
      // return the whole value if the data matches anywhere in the array
      if (filterMode === 'contains' || filterMode === '' || filterMode === undefined) {
        dataMatchesFilter = dataToCheck
      }  
    }
  }
  return dataMatchesFilter
}

/**
* Filter "associative array" [{"str":"str"}]
*   - Searches one level deep.
*   - Filter Mode settings:
*        * <contains|''|undefined> - loose search; returns whole object if even one *              match is found. This is the default.
*        * results - returns results only (does not include any other original values)
*        * strict - returns a match only if *all* filter criteria are met
*
* @param data {arr}
*        filterList {arr}
*        filterMode {str} - possible values: '', contains', 'results', 'strict'
*/
var FilterAssoc = function(data, filterList, filterMode) {
  // cache length for being nice to piler guy/gal
  var dataLength = data.length
  var filteredArray = []
  // loop through array to access the object literals
  for (var i = 0; i < dataLength; ++i) {
    var filterRes = _filterChoose(data[i], filterList, filterMode)
    // if results from our internal filter methods are NOT "null",
    // then we need those results!
    if (filterRes !== null) {
        // build our results
        filteredArray.push(filterRes)
    }
  }
  return filteredArray
}

var filteredData = FilterAssoc(data, filters, 'strict')

console.log(filteredData)
发布评论

评论列表(0)

  1. 暂无评论