【问题标题】:return value after filtering array inside an object of arrays在数组对象内过滤数组后返回值
【发布时间】:2018-09-21 10:19:50
【问题描述】:

我正在尝试创建一个使用函数返回对象数组的自动完成功能。我的对象是这样的:

this.vehiclesList =
  [
    {
      "additionalDriverContacts": [9929929929, 9992992933, 9873773777],
      "id": 1
    },
    {
      "additionalDriverContacts": [8388388388, 8939939999],
      "id": 2
    }
  ]

我想根据 additionalDriverContacts 过滤数组。

我的功能是这样的:

filterVehicleAdditionalMobile(val: string) {
     if (typeof val != 'string') {
            return [];
        }
    let value= val? this.vehiclesList.filter((item) => {
            if(item.additionalDriverContacts) 
                 item.additionalDriverContacts.forEach((option)=> {
                   String(option).toLowerCase().indexOf(val.toLowerCase()) != -1 
                })
             }
     }) : this.vehiclesList;
    console.log(value)
    return value;
}

但是在控制台中的值是空数组。我哪里做错了。我尝试在这个问题中寻找解决方案How do i filter an array inside of a array of objects? 但它没有帮助,因为我的用例不同。

我想要的结果应该是: 如果 99299 作为参数传递给 function ,则与该数字匹配的 additionalDriverContacts 应作为数组返回。 对于输入 99299,应返回 result = [9929929929,9992992933]

【问题讨论】:

  • 请注意,您最初拥有this.vehicleList,但您的代码后来使用: this.vehiclesList - 额外的s。此外,您的 String(option).. 行是一个孤立的表达式。
  • 代码中的任何地方都没有 JSON。它是一个 JavaScript 对象。我会一直指出这一点,直到我死的那一天。
  • 感谢您指出错误。我更新了它
  • @ChrisG 已编辑。谢谢
  • 你的过滤器没有返回任何东西,所以一切都被认为是假的,然后你什么也得不到:)

标签: javascript angular ecmascript-6 functional-programming


【解决方案1】:

对于输入99299,应返回结果=[9929929929,9992992933]

我们可以使用数组.map()提取联系人,然后用字符串.search()进行过滤:

const vehiclesList = [
    {"id": 1, "additionalDriverContacts": [9929929929, 9992992933, 9873773777]},
    {"id": 2, "additionalDriverContacts": [8388388388, 8939939999]}]

result = getMatchingContacts(vehiclesList, 99299) // run test
console.log(result)                               // show result

function getMatchingContacts(list, key) {  
  const arrayOfContacts = list.map(item => item.additionalDriverContacts)
  const contacts = [].concat(...arrayOfContacts)                       // flatten the nested array
    .filter(contact => contact.toString().search(key.toString()) >= 0) // find matches
  return contacts
}

希望这会有所帮助。

干杯,

【讨论】:

    【解决方案2】:

    所以你需要在这里做的是首先将vehiclesList中的每一项转换成匹配结果的数组,然后将它们连接在一起。

    试试这个:

    var vehiclesList = [{
        "additionalDriverContacts": [9929929929, 9992992933, 9873773777],
        "id": 1
      },
      {
        "additionalDriverContacts": [8388388388, 8939939999],
        "id": 2
      }
    ];
    
    function filterVehicleAdditionalMobile(val) {
      if (typeof val != 'string') {
        return [];
      }
      // array of arrays
      const values = vehiclesList.map((item) => {
          if (!item.additionalDriverContacts) { return []; }
          
          return item.additionalDriverContacts.filter((option) => 
              String(option).toLowerCase().indexOf(val.toLowerCase()) != -1
          );
      });
      
      console.log(values);
    
      // flatten
      return Array.prototype.concat.apply([], values);
    }
    
    console.log(filterVehicleAdditionalMobile('99'));

    或者,您可以将所有项目连接在一起,然后过滤它们。这样效率较低,但更简单,代码更少:

    var vehiclesList = [{
        "additionalDriverContacts": [9929929929, 9992992933, 9873773777],
        "id": 1
      },
      {
        "additionalDriverContacts": [8388388388, 8939939999],
        "id": 2
      }
    ];
    
    function flatten(values) {
        return Array.prototype.concat.apply([], values);
    }
    
    function filterVehicleAdditionalMobile(val) {
      if (typeof val != 'string') {
        return [];
      }
      
      return flatten(vehiclesList.map(v => v.additionalDriverContacts || []))
          .filter(option => String(option).toLowerCase().indexOf(val.toLowerCase()) != -1);
    }
    
    console.log(filterVehicleAdditionalMobile('99'));

    【讨论】:

    • 不,它不起作用。在安慰时,如果匹配,它会在数组中显示数组
    • @UdG 以上两个结果都生成一个数组,当您单击 Run code sn-p 按钮时可以看到。在第一个示例中,我在将值连接在一起之前记录了values 变量,因此请记住向下滚动以查看最终值。或者你是说当你把它改编成你自己的代码时它不会产生想要的结果?
    【解决方案3】:

    更新:问题的最后一次编辑

    尝试更改:

      filterVehicleAdditionalMobile(val: string) {
        if (typeof val !== 'string') {
          return [];
        }
    
        let driverContacts = [];
        this.vehiclesList.forEach((vehicule) => {
          if (vehicule.additionalDriverContacts) {
            if (val) {
              driverContacts = driverContacts.concat(vehicule.additionalDriverContacts.filter((driverContact) => {
                return String(driverContact).toLowerCase().indexOf(val.toLowerCase()) !== -1;
              }));
            } else {
              driverContacts = driverContacts.concat(vehicule.additionalDriverContacts);
            }
          }
        });
    
        return driverContacts;
      }
    

    测试:

    const driver = this.filterVehicleAdditionalMobile('8');
    console.log(driver);
    

    显示:

    0: 9873773777 1:8388388388 2:8939939999

    【讨论】:

    • 您的解决方案是返回所有数组项的列表,而不是特定匹配的数组项。语法错误也很少。
    • 我保留了您代码的逻辑,因为您在过滤器中不使用“val”,它会导致类似的结果
    • 您想让车辆保持 val 与附加的nalDriverContacts 之一匹配?
    • 所有匹配的值都应该在一个数组中
    • @UdG 你看过我的回答了吗?
    猜你喜欢
    • 2021-10-02
    • 2017-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-22
    • 2022-11-27
    • 2021-11-10
    相关资源
    最近更新 更多