首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >javascript (ES6):还有比"for循环“更有效的方式吗?

javascript (ES6):还有比"for循环“更有效的方式吗?
EN

Stack Overflow用户
提问于 2018-10-17 07:27:41
回答 3查看 489关注 0票数 4

这不是副本。请看我下面的评论!

有没有人知道比ES6中循环更有效的解决方案?

我写了以下内容,性能欠佳。有什么改进的想法吗?非常感谢。

基本上,我有一个关于汽车的对象和一个关于用户偏好的数组。预期的行为是将所有相关的汽车名称放入一个数组中。

用户可以提供任意数量的首选项。只有在首选项中提到了所有规范时,才应该推送汽车名称。因此,一些偏好将是“剩余物”。

出于这个原因,在下面的示例中出现了本田,但不是宝马,这是预期的(但非常慢的行为)。

代码语言:javascript
复制
// Car objects
const cars = [{
    name: "Honda",
    category: "eco",
    specs: {
      0: "green",
      1: "fast",
      2: "automatic"
    }
  },
  {
    name: "BMW",
    category: "sport",
    specs: {
      0: "blue",
      1: "fast",
      2: "automatic"
    }
  }
]

// User preferences
const preferences = ["green", "fast", "4x4", "automatic", "panorama"]

// function to get length/amount of car specifications
function objsize(Myobj) {
  var osize = 0,
    key;
  for (key in Myobj) {
    if (Myobj.hasOwnProperty(key)) osize++;
  }
  return Object(osize);
};


//function to check if ALL specifications are included in the user preferences
function checkSpecs(spec_item) {
  return preferences.includes(spec_item)
}

// main function
function filter_func() {

  //final results
  let matched_cars = []


  for (i = 0; i < objsize(cars); i++) {

    let specs_collector = []

    for (j = 0; j < objsize(cars[i].specs); j++) {
      specs_collector.push(cars[i].specs[j])
    }

    if (specs_collector.every(checkSpecs) === true) {
      matched_cars.push(cars[i].name)
      specs_collector = []
    }

  }
  console.log(matched_cars)
}

filter_func()

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-10-17 07:58:30

你不能不看每一辆车,也不能不看每一辆车的规格,因为你想测试每一辆车。通过使用Set,您可以避免每次循环遍历首选项。

因此,这可能会更快,也可能不会更快,但它要简单得多,也更容易理解,因为代码读起来几乎像英语: filter cars,其中每个规范都在首选项中:

代码语言:javascript
复制
// Car objects
const cars = [{
    name: "Honda",
    category: "eco",
    specs: ["green", "fast","automatic"]
    },
  {
    name: "BMW",
    category: "sport",
    specs: ["blue", "fast","automatic"]
    }
]

const preferences = new Set(["green", "fast", "4x4", "automatic", "panorama"])

let filtered = cars.filter(car => car.specs.every(spec => preferences.has(spec)))
console.log(filtered)

票数 9
EN

Stack Overflow用户

发布于 2018-10-17 07:58:41

-编辑--

使用操作中的数据:

代码语言:javascript
复制
const array_intersect = (a, b) => a.filter( i => (b.indexOf(i) >= 0) )
const a_contains_b = (a, b) => array_intersect(a, b).length == b.length

var cars = [{
    name: "Honda",
    category: "eco",
    specs: ["green", "fast", "automatic"]
  },
  {
    name: "BMW",
    category: "sport",
    specs: ["blue", "fast", "automatic"]
  }
]

const preferences = ["green", "fast", "4x4", "automatic", "panorama"]

let filtered = cars.filter(car => a_contains_b(preferences, car.specs))
console.log(filtered);

票数 2
EN

Stack Overflow用户

发布于 2018-10-17 09:58:17

至少有一个循环是无法逃脱的。你总是要在所有的车里循环,不管是for...或者使用另一个构造,如array.filter()。但是,还有另一种方法可以获得性能。您可以使用位掩码。这将需要更改car对象的数据结构,以便每辆汽车已经包含与其规格相对应的位掩码,并且当用户选择所需的规格时,同样应该添加规格代码。(然而,我怀疑这可能会带来很大的麻烦,但收获很少。)

代码语言:javascript
复制
// Let's pretend there are preset binary digits corresponding 
// to each one of the available preferences:
//
//     "blue" => 1
//     "green" => 2
//     "red" => 4
//     "fast" => 8
//     "slow" => 16
//     "automatic" => 32
//     "4x4"  => 64
//     "panorama" => 128
//
// You would encode this into the data before processing

var cars = [{
    name: "Honda",
    category: "eco",
    specs: ["green", "fast", "automatic"],
    bin_specs: 42 // 2 + 8 + 32
  },
  {
    name: "BMW",
    category: "sport",
    specs: ["blue", "fast", "automatic"],
    bin_specs: 41 // 1 + 8 + 32
  }
]

const preferences = ["green", "fast", "4x4", "automatic", "panorama"]
const bin_preferences = 234 // 2 + 8 + 64 + 32 + 128]

let filtered = cars.filter(car => (car.bin_specs & bin_preferences) === car.bin_specs)

console.log(filtered);

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52845297

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档