【问题标题】:Loop through list of maps to filter map key-values using JS循环遍历映射列表以使用 JS 过滤映射键值
【发布时间】:2018-08-22 14:48:53
【问题描述】:

如何循环遍历映射列表以从下面使用 JS 的具有记录映射的列表中过滤掉 SearchMap 键值?

地图

var searchMap = new Map()
searchMap.set("ed_mood", "strong")
searchMap.set("ed_target_audience", "Expert")
searchMap.set("ed_clip_type", "intro")

列表

var master_data =
[
    {ed_mood: "Light", ed_rating: 10, ed_target_audience: "Novice", ed_clip_type: "Basic"},
    {ed_mood: "Light", ed_rating: 5, ed_target_audience: "Expert", ed_clip_type: "Q&A"},
    {ed_mood: "Strong", ed_rating: 8, ed_target_audience: "Expert", ed_clip_type: "Intro"},
    {ed_mood: "Strong", ed_rating: 7, ed_target_audience: "Expert", ed_clip_type: "Q&A"},
    {ed_mood: "Strong", ed_rating: 10, ed_target_audience: "Expert", ed_clip_type: "intro"}
]

注意:为了过滤掉我正在使用 AlaSql 的记录,但它没有给出预期的结果。还有其他 JS 方式将地图过滤到地图列表吗?

var filter_result = [];
searchMap.forEach(function(value, key){
    var data  = alasql(`select * from ? where ${key} like ?`,[master_data, `%${value}%`]);
    $.each(data, (i) => filter_result.push(data[i]));
});

预期结果

[
   {ed_mood: "Strong", ed_rating: 8, ed_target_audience: "Expert", ed_clip_type: "Intro"},
   {ed_mood: "Strong", ed_rating: 10, ed_target_audience: "Expert", ed_clip_type: "intro"}
]

【问题讨论】:

    标签: javascript jquery list dictionary alasql


    【解决方案1】:

    您的代码中的问题是您使用(隐式)OR 运算符连接条件。您的预期结果表明您应该使用AND 运算符。

    您可以先构建您的 SQL 命令,然后使用 AlaSQL 执行它(只是一个建议,您向我介绍了 AlaSQL :-))

    var searchMap = new Map();
    searchMap.set("ed_mood", "strong");
    searchMap.set("ed_target_audience", "Expert");
    searchMap.set("ed_clip_type", "intro");
    
    var master_data =
    [
        {ed_mood: "Light", ed_rating: 10, ed_target_audience: "Novice", ed_clip_type: "Basic"},
        {ed_mood: "Light", ed_rating: 5, ed_target_audience: "Expert", ed_clip_type: "Q&A"},
        {ed_mood: "Strong", ed_rating: 8, ed_target_audience: "Expert", ed_clip_type: "Intro"},
        {ed_mood: "Strong", ed_rating: 7, ed_target_audience: "Expert", ed_clip_type: "Q&A"},
        {ed_mood: "Strong", ed_rating: 10, ed_target_audience: "Expert", ed_clip_type: "intro"}
    ];
    
    var command = "SELECT * FROM ? WHERE";
    var values = [];
    
    searchMap.forEach(function(value, key){
    	command += ` ${key} LIKE ? AND`;
    	values.push('%' + value);
    });
    
    //Removing the last "AND"
    command = command.substring(0, command.length -4);
    
    var filter_result = alasql(command, [master_data, ...values]);
    
    console.log(filter_result);
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/alasql/0.4.5/alasql.min.js"></script>

    没有 AlaSQL 的解决方案

    使用 ES6,您的代码可能是:

    var searchMap = new Map();
    searchMap.set("ed_mood", "strong");
    searchMap.set("ed_target_audience", "Expert");
    searchMap.set("ed_clip_type", "intro");
    
    var master_data =
    [
        {ed_mood: "Light", ed_rating: 10, ed_target_audience: "Novice", ed_clip_type: "Basic"},
        {ed_mood: "Light", ed_rating: 5, ed_target_audience: "Expert", ed_clip_type: "Q&A"},
        {ed_mood: "Strong", ed_rating: 8, ed_target_audience: "Expert", ed_clip_type: "Intro"},
        {ed_mood: "Strong", ed_rating: 7, ed_target_audience: "Expert", ed_clip_type: "Q&A"},
        {ed_mood: "Strong", ed_rating: 10, ed_target_audience: "Expert", ed_clip_type: "intro"}
    ];
    
    var filter_result = master_data.filter(function(x) {
        for (var [key, value] of searchMap) {
            //Change the comparison to fit your needs
        
            // Condition to handle null , undefined and ''(blank) values
            if (x[key] !== null && typeof x[key] !== 'undefined' && x[key] !== '') {
                if (x[key].toLowerCase() !== value.toLowerCase()) return false;
            } else {
                return false;
            }
        }
        return true;
    });
    
    console.log(filter_result);
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/alasql/0.4.5/alasql.min.js"></script>

    【讨论】:

    • 第二个sn-p中不需要引用alasql。它目前导致“SecurityError:操作不安全”。通过删除对alasql 的引用,输出中没有错误。对于第一个 sn-p,唉,我没有解决方法。对不起! (它很可能在 jsFiddle 中工作得很好。)
    【解决方案2】:

    以下代码 filters master_data 仅匹配 searchMap 中的每个 paramreturn Objects

    有关详细信息,请参阅Array.prototype.filter()Array.prototype.every()Map.entries()JSON.stringify()String.toLowercase()

    // Search Map.
    const searchMap = new Map([
      ['ed_mood', 'strong'],
      ['ed_target_audience', 'Expert'],
      ['ed_clip_type', 'intro']
    ])
    
    // Master Data.
    const master_data = [
      {ed_mood: 'Light', ed_rating: 10, ed_target_audience: 'Novice', ed_clip_type: 'Basic'},
      {ed_mood: 'Light', ed_rating: 5, ed_target_audience: 'Expert', ed_clip_type: 'Q&A'},
      {ed_mood: 'Strong', ed_rating: 8, ed_target_audience: 'Expert', ed_clip_type: 'Intro'},
      {ed_mood: 'Strong', ed_rating: 7, ed_target_audience: 'Expert', ed_clip_type: 'Q&A'},
      {ed_mood: 'Strong', ed_rating: 10, ed_target_audience: 'Expert', ed_clip_type: 'intro'}
    ]
    
    // Output.
    const output = 
      
      // Filter master_data for Objects that include every searchpoint.
      master_data.filter((datapoint) =>
       
      // Destructuring assignment + Map.entries to reveal searchMap entries.
      [...searchMap.entries()].every((searchpoint) =>
      
      // Object.entries() to reveal datapoint entries. 
      // JSON.stringify + toLowerCase() for normalization.
      JSON.stringify(Object.entries(datapoint)).toLowerCase().includes(JSON.stringify(searchpoint).toLowerCase())))
    
    
    // Log.
    console.log(output)

    【讨论】:

    • 对于很少的工作来说,这不是太多的代码。我认为在这种情况下,表达性代码会比描述性更好。虽然对于理解部分,很高兴!此外,这是太多的计算,对每个条目进行字符串化并使用 String.includes 检查条目的值是否存在,这是一个 *overkill•。
    • 代码原为1 line。我将其拆分为3 并添加了comments 以帮助提问者了解发生了什么。 JSON.stringify() 廉价地标准化数据以进行有效比较。如果您认为存在一个更简洁/有效的解决方案,请随时发布?
    • 我宁愿不字符串化。我会做一个searchMatchers = Object.keys(searchMap).map(function(data){ return [data,searchMap[data]]; }); 然后,const endResult = master_data.filter(dataObj =&gt; { return searchMatchers.every(([key, value]) =&gt; { return dataObj[key] === value; }) })
    【解决方案3】:

    你可以在这里使用 lodash 的 filter 方法。

    在你的情况下,你会这样做:

    const result = _filter(master_data, {
      ed_mood: 'strong',
      ed_target_audience: 'expert',
      ed_clip_type: 'intro'
    });
    

    lodash/filter了解更多信息

    【讨论】:

      猜你喜欢
      • 2021-11-22
      • 2023-03-15
      • 2012-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-31
      • 1970-01-01
      相关资源
      最近更新 更多