JavaScript (ES6): какой-нибудь более эффективный способ, чем «для циклов»? - PullRequest
0 голосов
/ 17 октября 2018

это не дубликат.пожалуйста, смотрите мой комментарий ниже!

Кто-нибудь знает более эффективное решение, чем для циклов в ES6?

Я написал следующее, что не хватает производительности,Есть идеи по улучшению?Высоко ценится.

В основном у меня есть объект, касающийся автомобилей, и массив, касающийся пользовательских предпочтений.Ожидаемое поведение - поместить все соответствующие имена автомобилей в массив.

Пользователи могут предоставить любое количество предпочтений.Название автомобиля следует нажимать только в том случае, если В настройках указаны ВСЕ характеристики.Поэтому некоторые предпочтения будут «остатками».

По этой причине в следующем примере появляется Honda, но не BMW, что является ожидаемым (но очень медленным поведением).

// 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()

Ответы [ 3 ]

0 голосов
/ 17 октября 2018

- РЕДАКТИРОВАТЬ -

Использование данных в ОП:

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);
0 голосов
/ 17 октября 2018

Нет способа избежать хотя бы одной петли.Вы всегда должны проходить через все машины, будь то с помощью for ... или с другой конструкцией, например array.filter ().Но есть и другой способ получить производительность.Вы можете использовать битовые маски.Это потребует изменения структуры данных автомобильного объекта так, чтобы каждый автомобиль уже содержал битовую маску, соответствующую его спецификациям, и когда пользователь выбирает желаемые спецификации, также должны добавляться коды спецификаций.(Тем не менее, я подозреваю, что это может быть слишком хлопотно для небольшой выгоды.)

// 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);
0 голосов
/ 17 октября 2018

Вы не можете не смотреть на каждую машину, и вы не можете не смотреть на каждую спецификацию автомобиля, потому что вы хотите проверить каждую из них.Вы можете избежать зацикливания на предпочтениях каждый раз, используя Set .

Так что это может или не может быть быстрее, но это намного проще и намного проще для понимания, потому что код почти читается как английский: фильтруйте автомобили, где каждая спецификация находится в настройках:

// 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...