【问题标题】:How to filter through a JavaScript array using array.filter() method?如何使用 array.filter() 方法过滤 JavaScript 数组?
【发布时间】:2019-10-08 15:18:54
【问题描述】:

我有一个 JavaScript 对象 (filters),它具有布尔值。我还有一组对象 (mainSubArray)。基于 JavaScript Object,如果布尔值为 true,我想返回一个新数组 (filteredArray),如果布尔值为 false,则不返回新数组。

到目前为止,我已经尝试了以下方法:

// The main array that needs to be filtered
const mainSubArray = [{
    MenB_Classification: "NOT Required",
    CONTROL: "Public",
    Enrollment: "892"
  },
  {
    MenB_Classification: "Required",
    CONTROL: "Private",
    Enrollment: "1601"
  },
  {
    MenB_Classification: "NOT Required",
    CONTROL: "Private",
    Enrollment: "447"
  },
  {
    MenB_Classification: "NOT Required",
    CONTROL: "Public",
    Enrollment: "1203"
  },
  {
    MenB_Classification: "Required",
    CONTROL: "Private",
    Enrollment: "32"
  },
  {
    MenB_Classification: "NOT Required",
    CONTROL: "Public",
    Enrollment: "98"
  },
  {
    MenB_Classification: "Recommended",
    CONTROL: "Private",
    Enrollment: "654"
  },
  {
    MenB_Classification: "NOT Required",
    CONTROL: "Private",
    Enrollment: "345318"
  },
  {
    MenB_Classification: "NOT Required",
    CONTROL: "Private",
    Enrollment: "13324"
  },
  {
    MenB_Classification: "Recommended",
    CONTROL: "Private",
    Enrollment: "39"
  },
  {
    MenB_Classification: "NOT Required",
    CONTROL: "Private",
    Enrollment: "4"
  },
  {
    MenB_Classification: "NOT Required",
    CONTROL: "Private",
    Enrollment: "910"
  },
  {
    MenB_Classification: "NOT Required",
    CONTROL: "Private",
    Enrollment: "23453"
  }
]


// Object with boolean values
var filters = {
  required: true,
  recomended: true,
  notRequired: false,
  publics: true,
  privates: true,
  ennrollmentOne: true,
  ennrollmentTwo: false,
  ennrollmentThree: false,
  ennrollmentFour: false,
}

// New Array using array.filter() method
var filteredArray = mainSubArray.filter(function(d) {
  if ((filters.required == true && d.MenB_Classification === 'Required') || (filters.recomended === true && d.MenB_Classification === 'Recommended') || (filters.notRequired === true && d.MenB_Classification === 'NOT Required') || (filters.publics === true && d.CONTROL === 'Public') || (filters.privates === true && d.CONTROL === 'Private') || (filters.ennrollmentOne === true && d.Enrollment < 100) || (filters.ennrollmentTwo === true && d.Enrollment >= 100 && d.Enrollment < 1000) || (filters.ennrollmentThree === true && d.Enrollment >= 1000 && d.Enrollment < 5000) || (filters.ennrollmentThree === true && d.Enrollment > 5000)) {
    return true;
  } else {
    return false;
  }

});

console.log(filteredArray);

当我 console.log(filteredArray) 时,我会取回原始数组。

输出应该是一个新数组,其中仅包含 filters 对象中设置为 true 的值。

【问题讨论】:

  • 我试过你的代码,它看起来原始数组 mainSubArray 有 13 项,过滤数组过滤数组里面有 12 项,区别是 {MenB_Classification: "NOT Required", CONTROL: "33033764030", Enrollment: "345318 "}
  • filters 在做什么?为什么它没有与对象的值直接可比较的值?
  • 您希望过滤后的数组是什么样的?现在我认为问题出在你的逻辑上,因为你使用了 9 或 10 个不同的 or 语句,它几乎总是匹配其中一个。我还建议写someBoolean &amp;&amp; 而不是someBoolean === true &amp;&amp;
  • 过滤器函数中的 if 条件涵盖了所有内容,这就是为什么您将原始数组视为过滤器的结果
  • 所以,如果 ANY 的过滤器为真,则包含该项目!?还是应该只包含所有过滤器都适用的项目?

标签: javascript arrays javascript-objects


【解决方案1】:

您可以将字符串数组作为过滤器对象的键,并根据函数检查对象的所需键及其所需值。

在过滤器函数中迭代关键函数数组,如果需要一个函数并且结果为true,则提前退出。

结果是原始 13 个对象中的 12 个对象组成的数组。

var data = [{ MenB_Classification: "NOT Required", CONTROL: "Public", Enrollment: "892" }, { MenB_Classification: "Required", CONTROL: "Private", Enrollment: "1601" }, { MenB_Classification: "NOT Required", CONTROL: "Private", Enrollment: "447" }, { MenB_Classification: "NOT Required", CONTROL: "Public", Enrollment: "1203" }, { MenB_Classification: "Required", CONTROL: "Private", Enrollment: "32" }, { MenB_Classification: "NOT Required", CONTROL: "Public", Enrollment: "98" }, { MenB_Classification: "Recommended", CONTROL: "Private", Enrollment: "654" }, { MenB_Classification: "NOT Required", CONTROL: "33033764030", Enrollment: "345318" }, { MenB_Classification: "NOT Required", CONTROL: "Private", Enrollment: "13324" }, { MenB_Classification: "Recommended", CONTROL: "Private", Enrollment: "39" }, { MenB_Classification: "NOT Required", CONTROL: "Private", Enrollment: "4" }, { MenB_Classification: "NOT Required", CONTROL: "Private", Enrollment: "910" }, { MenB_Classification: "NOT Required", CONTROL: "Private", Enrollment: "23453" }],
    filters = {
        required: true,
        recomended: true,
        notRequired: false,
        publics: true,
        privates: true,
        ennrollmentOne: true,
        ennrollmentTwo: false,
        ennrollmentThree: false,
        ennrollmentFour: false,
    },
    fn = [
        ['required', o => o.MenB_Classification === 'Required'],
        ['recomended', o => o.MenB_Classification === 'Recommended'],
        ['notRequired', o => o.MenB_Classification === 'NOT Required'],
        ['publics', o => o.CONTROL === 'Public'],
        ['privates', o => o.CONTROL === 'Private'],
        ['ennrollmentOne', o => o.Enrollment < 100],
        ['ennrollmentTwo', o => o.Enrollment >= 100 && o.Enrollment < 1000],
        ['ennrollmentThree', o => o.Enrollment >= 1000 && o.Enrollment < 5000],
        ['ennrollmentFour', o => o.Enrollment >= 5000]
    ],
    result = data.filter(o => fn.some(([k, f]) => filters[k] && f(o)));

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

【讨论】:

    【解决方案2】:

    它有效,但您的条件几乎涵盖了所有情况。

    即使在您的情况下,它也可以作为结果包含 12 个元素而不是 13 个。 它不包含:

    {
        MenB_Classification: "NOT Required",
        CONTROL: "33033764030",
        Enrollment: "345318"
      },
    

    【讨论】:

    • 只是确认问题不存在。初始解决方案工作正常。其他代码只是为了让它更优雅
    【解决方案3】:

    我假设你想这样做:

    var data = [{ MenB_Classification: "NOT Required", CONTROL: "Public", Enrollment: "892" }, { MenB_Classification: "Required", CONTROL: "Private", Enrollment: "1601" }, { MenB_Classification: "NOT Required", CONTROL: "Private", Enrollment: "447" }, { MenB_Classification: "NOT Required", CONTROL: "Public", Enrollment: "1203" }, { MenB_Classification: "Required", CONTROL: "Private", Enrollment: "32" }, { MenB_Classification: "NOT Required", CONTROL: "Public", Enrollment: "98" }, { MenB_Classification: "Recommended", CONTROL: "Private", Enrollment: "654" }, { MenB_Classification: "NOT Required", CONTROL: "33033764030", Enrollment: "345318" }, { MenB_Classification: "NOT Required", CONTROL: "Private", Enrollment: "13324" }, { MenB_Classification: "Recommended", CONTROL: "Private", Enrollment: "39" }, { MenB_Classification: "NOT Required", CONTROL: "Private", Enrollment: "4" }, { MenB_Classification: "NOT Required", CONTROL: "Private", Enrollment: "910" }, { MenB_Classification: "NOT Required", CONTROL: "Private", Enrollment: "23453" }],
        filters = {
            required: true,
            recomended: true,
            notRequired: false,
            publics: true,
            privates: true,
            ennrollmentOne: true,
            ennrollmentTwo: false,
            ennrollmentThree: false,
            ennrollmentFour: false,
        },
        filteredArray = data.filter(function (d) {
          return ( // check MenB_Classification
               (filters.required && d.MenB_Classification === "Required")
            || (filters.recomended && d.MenB_Classification === "Recommended")
            || (filters.notRequired && d.MenB_Classification === "NOT Required")
          ) && ( // check CONTROL
               (filters.publics && d.CONTROL === "Public")
            || (filters.privates && d.CONTROL === "Private")
          ) && ( // check Enrollment
               (filters.ennrollmentOne && d.Enrollment < 100)
            || (filters.ennrollmentTwo && d.Enrollment >= 100 && d.Enrollment < 1000)
            || (filters.ennrollmentThree && d.Enrollment >= 1000 && d.Enrollment < 5000)
            || (filters.ennrollmentFour && d.Enrollment > 5000)
          );
        });
    
    console.log(filteredArray);

    这里有一个更详细的版本。我已经为每个属性将过滤器分成一个函数:

    我不知道这是否与您相关,但我还添加了没有为属性设置过滤器的情况。

    function filterByClassification(d){
        return (filters.required && d.MenB_Classification === "Required")
            || (filters.recomended && d.MenB_Classification === "Recommended")
            || (filters.notRequired && d.MenB_Classification === "NOT Required")
            // or no filter set for MenB_Classification
            || (!filters.required && !filters.recomended && !filters.notRequired);
    }
    
    function filterByControl(d){
        return (filters.publics && d.CONTROL === "Public")
            || (filters.privates && d.CONTROL === "Private")
            // or no filter set for CONTROL
            || (!filters.publics && !filters.privates);
    }
    
    function filterByEnrollment(d){
        return (filters.ennrollmentOne && d.Enrollment < 100)
            || (filters.ennrollmentTwo && d.Enrollment >= 100 && d.Enrollment < 1000)
            || (filters.ennrollmentThree && d.Enrollment >= 1000 && d.Enrollment < 5000)
            || (filters.ennrollmentFour && d.Enrollment > 5000)
            // or no filter set for Enrollment
            || (!filters.ennrollmentOne && !filters.ennrollmentTwo && !filters.ennrollmentThree && !filters.ennrollmentFour); 
    }
    
    
    filteredArray = data.filter(function (d) {
        // for every property, there must be one filter fulfilled
        return filterByClassification(d) 
            && filterByControl(d) 
            && filterByEnrollment(d);
    });
    

    而您的代码相当于:

    filteredArray = data.filter(function (d) {
        // if any condition at all is fulfilled, keep the item
        return filterByClassification(d) 
            || filterByControl(d) 
            || filterByEnrollment(d);
    });`
    

    【讨论】:

    • 我很难弄清楚我们的代码之间的差异以及为什么您的代码有效而我的无效。无论如何,谢谢你。这正是我想要的。
    • @NigelDcruz 我有点着急。我按属性对条件进行分组。 每个属性至少有一个条件必须是true。您的代码只是询问是否满足任何条件。因此,如果满足 filters.required,它就不再关心 CONTROL 或 Enrollment 的过滤器。
    • @NigelDcruz 我添加了一个更详细的示例
    【解决方案4】:

    不,filteredArray 与主数组不同。您可以记录长度以轻松感受差异。

    此外,if else 可以避免仅在所有条件下使用 return。

    // The main array that needs to be filtered
    const mainSubArray = [{
        MenB_Classification: "NOT Required",
        CONTROL: "Public",
        Enrollment: "892"
      },
      {
        MenB_Classification: "Required",
        CONTROL: "Private",
        Enrollment: "1601"
      },
      {
        MenB_Classification: "NOT Required",
        CONTROL: "Private",
        Enrollment: "447"
      },
      {
        MenB_Classification: "NOT Required",
        CONTROL: "Public",
        Enrollment: "1203"
      },
      {
        MenB_Classification: "Required",
        CONTROL: "Private",
        Enrollment: "32"
      },
      {
        MenB_Classification: "NOT Required",
        CONTROL: "Public",
        Enrollment: "98"
      },
      {
        MenB_Classification: "Recommended",
        CONTROL: "Private",
        Enrollment: "654"
      },
      {
        MenB_Classification: "NOT Required",
        CONTROL: "33033764030",
        Enrollment: "345318"
      },
      {
        MenB_Classification: "NOT Required",
        CONTROL: "Private",
        Enrollment: "13324"
      },
      {
        MenB_Classification: "Recommended",
        CONTROL: "Private",
        Enrollment: "39"
      },
      {
        MenB_Classification: "NOT Required",
        CONTROL: "Private",
        Enrollment: "4"
      },
      {
        MenB_Classification: "NOT Required",
        CONTROL: "Private",
        Enrollment: "910"
      },
      {
        MenB_Classification: "NOT Required",
        CONTROL: "Private",
        Enrollment: "23453"
      }
    ]
    
    
    // Object with boolean values
    var filters = {
      required: true,
      recomended: true,
      notRequired: false,
      publics: true,
      privates: true,
      ennrollmentOne: true,
      ennrollmentTwo: false,
      ennrollmentThree: false,
      ennrollmentFour: false,
    }
    
    // New Array using array.filter() method
    var filteredArray = mainSubArray.filter(function(d) {
      return ((filters.required && d.MenB_Classification === 'Required') || (filters.recomended && d.MenB_Classification === 'Recommended') || (filters.notRequired && d.MenB_Classification === 'NOT Required') || (filters.publics && d.CONTROL === 'Public') || (filters.privates && d.CONTROL === 'Private') || (filters.ennrollmentOne && d.Enrollment < 100) || (filters.ennrollmentTwo && d.Enrollment >= 100 && d.Enrollment < 1000) || (filters.ennrollmentThree && d.Enrollment >= 1000 && d.Enrollment < 5000) || (filters.ennrollmentThree && d.Enrollment > 5000));
    });
    console.log(mainSubArray.length)
    console.log(filteredArray.length);

    【讨论】:

    • @TylerRoper 嘿,伙计,这不是问题,而是混乱。在控制台上记录长度的建议是消除他的困惑的解决方案。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-02
    • 1970-01-01
    • 2017-08-28
    • 2021-02-22
    • 2016-11-02
    相关资源
    最近更新 更多