@kikosko

Как парсить строку в оператор сравнения?

Я реализовал метод для фильтрации товаров по указанным опциям. Метод принимает в качестве параметра объект options, который содержит параметры для поиска, например: {name: "item 2", price: "<= 1000", count: "> 2"}, каждый из параметров является опциональными. Метод должен возвращать отфильтрованный массив с товарами. filterProductBy (options).
Мне удалось фильтровать по имени. Скажите, как правильно фильтровать по числу
обязательное условие передачи в таком виде:
console.log(shop.filterProductsBy({ 
name: "product", 
count: ">=10", 
price: ">=200" }));

Весь код:
//Product Creation Class
class Product {
    constructor(name, count, price) {
        this.name = name;
        this.count = count;
        this.price = price;
    }
}
//Сlass where products are recorded
class Shop {
    constructor(products) {
        this.products = [];
    }
    //method for adding a product
    addProduct(newProduct) {
        this.products.push(newProduct);
    }
    //method for filtering products by specified parameters
    filterProductBy(options) {
        const optionName = options.name,
            optionCount = options.count,
            optionPrice = options.price;

        const filters = {
            byName: function (actualName, optionName) {
                return (actualName === undefined) || (actualName === optionName);
            },

            byCount: function (actualCount, optionCount) {
                return (actualCount === undefined) || (actualCount === optionCount);
            },

            byPrice: function (actualPrice, optionPrice) {
                return (actualPrice === undefined) || (actualPrice === optionPrice);
            }
    };
        return this.products.filter(
            (product) => filters.byName(product.name, optionName)
            || filters.byCount(product.count, optionCount)
            || filters.byPrice(product.price, optionPrice));
        }
}
const shop = new Shop();
shop.addProduct(new Product("product 1", 1, 2000));
shop.addProduct(new Product("item 2", 2, 100));
shop.addProduct(new Product("some 3", 3, 500));
shop.addProduct(new Product("anything 4", 4, 1000));
console.log(shop.filterProductBy({
name: "product 1",
count: ">1",
price: "<=1000"}));
  • Вопрос задан
  • 161 просмотр
Решения вопроса 1
@Ridz
kikosko
const filters = {
            byName: optionName == undefined ? () => undefined : (actualName, optionName) => actualName === optionName,

            byCount: optionCount == undefined ? () => undefined : new Function("actualName, optionName", "return actualName " +optionCount),

            byPrice: optionPrice == undefined ? () => undefined : new Function("actualName, optionName", "return actualName " +optionPrice)
       };
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
rockon404
@rockon404
Frontend Developer
Все это никак не пересекается с реальными задачами. Так никто не делает. Фильтры в магазинах реализуют по-другому. Вся задача сводится к тому, чтобы передать набор параметров на сервер и получить ответ с коллекцией.
Впустую тратите время.
Ответ написан
@Finch_85
Странная реализация фильтра. Но если обязательное условие ввод трех параметров для фильтра, то вот рабочий вариант - https://codepen.io/anon/pen/JZEWEB?editors=1111

П.С. И да, я повторю что поиск по имени так работать не будет, ибо нужно вводить точное соответствие названия товара - Product 1 === Product 1
Кроме того, нужно сделать так чтобы можно было указывать любое количество фильтров. То есть, искать только по цене и названию, или количеству и цене и т.д. А вот как это сделать уже догадайся сам))

Вот видимо то что надо - https://github.com/klesarev/test-lessons Делал это в свое время в качестве тестовго задания. Посмотри.
Ответ написан
@cppjunkie
А как насчет такого:

function evaluateFilter(filterExpr, param) {
  // Это проверка чтобы всякий нехороший JS-код в eval() не передавался
  if (!/^(>|<|>=|<=|==|!=)\s*[0-9]+$/.test(filterExpr)) {
    throw new Error('Invalid filter expression');
  }
  // param надо перегнать в число чтобы через него тоже не передавали чего попало
  return eval(Number(param) + filterExpr);
}

console.log(evaluateFilter('>=200', 1000));
console.log(evaluateFilter('>200', 100));
console.log(evaluateFilter('==200', 200));
evaluateFilter('alert("hello world")', 0);


Обычно eval() не очень рекомендуется использовать, т.к. через него любой код можно выполнять, но если как следует проверять входные данные то почему бы и нет. Хотя проще наверное свой урезанный eval написать для таких сравнений простых.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы