@kikosko

Почему не работает фильтр по свойствам класса?

Я хочу реализовать метод для фильтрации товаров по указанным опциям. Метод принимает в качестве параметра объект options, который содержит параметры для поиска например: {name: "item 2", price: "<= 1000", count: "> = 2"}, каждый из параметров является опциональными. Метод должен возвращать отфильтрованный массив с товарами. filterProductBy (options) .
//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) {
        let {name, count, price} = options;
        const getEvaluation = filterString => filterString.indexOf('>=') > -1 ?
            (number, amount) => number >= amount :
            (number, amount) => number <= amount;

            name.filter(product => name === undefined || 
            product.name === this.name);

            count.filter(product => count === undefined || 
            getEvaluation(count)(product.count, count.match(/(\d+)/)[0]));

        price.filter(product => price === undefined || 
        getEvaluation(price)(product.price, price.match(/(\d+)/)[0]));
    }
    
}
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: "anything 4",
    count: ">3",
    price: ">=500"
}));
  • Вопрос задан
  • 82 просмотра
Решения вопроса 1
@ned4ded
Верстка, Фронтенд
В целом, вы, похоже, просто запутались в в контексте и ссылках:

name.filter(product => name === undefined || product.name === this.name); 
// в этом месте вы пытаетесь отфильтровать переданную опцию name, которая является строкой "anything 4",
// так же контекст this.name - будет undefined, потому что в данном случае вы передаете стрелочную функцию, 
// this которой будет ссылаться на объект, в котором она была создана, т.е. - на Shop. У Shop нет свойства name
// правильный вариант: 
const filtered = this.products.filter(product => {
 return product.name === undefined || product.name === name
});


Все последующие функции вам нужно отредактировать по тому же принципу.

PS.
Не совсем понимаю, зачем вам парсить строчные операторы сравнения, когда можно просто отправлять функцию сравнения в метод фильтрации.

class Shop {
    constructor(products) {
        this.products = [];
    }

    addProduct(newProduct) {
        this.products.push(newProduct);
    }

    filterProduct(fn) {
      return this.products.filter(fn);
    }
    
}
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));

const filtered = shop.filterProduct((product) => product.name === 'anything 4' && product.count > 3 && product.price >= 500);

// console.log(filtered): [ Product { name: 'anything 4', count: 4, price: 1000 } ]


На самом деле, есть еще много мелких моментов:
1) С данными лучше работать функционально и не допускать добавления, удаление и проч. операции в текущем объекте, т.е. объект должен быть иммутабельным. При добавлении товара нужно создавать новый объект Shop.

2) Вытекает из первого - зачем вам в конструкторе Shop сигнатура products, когда вы ее не используете? По сути, ее должно использовать именно для сохранения передаваемого массива продуктов.

3) В объектах, работающих с данными, особенно когда идет фильтрация, сортировка и проч операции, лучше сразу имплементировать fluent-interface.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

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

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