Как обойти бессмысленную проверку array.filter - программирование
Подтвердить что ты не робот

Как обойти бессмысленную проверку array.filter

У меня есть 2 входа для фильтрации arrProd (см. Код ниже). В функции FormSubmit я сначала проверяю, являются ли значения price.minPrice и price.maxPrice действительными числами, а не пустыми строками. После этих проверок могут быть только две опции: либо пользователь пишет и вводит цифры, либо оставляет поля пустыми. Затем я проверяю, начались ли числа, затем массив фильтруется. В цикле фильтрации бессмысленно проверять значение несколько раз. Как я могу сделать это, чтобы проверить это только один раз?

import React, { Fragment, useCallback, useState } from "react";
import ReactDOM from "react-dom";

const arrProd = [
  {
    price: "5.75",
    sold: "100"
  },
  {
    price: "2.36",
    sold: "15"
  },
  {
    price: "5.48",
    sold: "20"
  },
  {
    price: "4.49",
    sold: "200"
  },
  {
    price: "3.15",
    sold: "258"
  },
  {
    price: "9.99",
    sold: "479"
  },
  {
    price: "4.8",
    sold: "147"
  },
  {
    price: "8",
    sold: "951"
  },
  {
    price: "4.27",
    sold: "753"
  },
  {
    price: "2.46",
    sold: "852"
  },
  {
    price: "4.99",
    sold: "742"
  },
  {
    price: "3.49",
    sold: "10"
  },
  {
    price: "2",
    sold: "26"
  },
  {
    price: "3.83",
    sold: "39"
  },
  {
    price: "9.98",
    sold: "47"
  },
  {
    price: "6.77",
    sold: "96"
  }
];

function App() {
  const [price, setPrice] = useState({ maxPrice: "", minPrice: "" });
  const [sold, setSold] = useState("");
  const [processingProd, setProcessingProd] = useState([]);
  const [checkInput, setCheckInput] = useState({
    checkPrice: false,
    checkSold: false
  });

  const PriceMaxMin = useCallback(({ target: { value, name } }) => {
    name === "maxPrice"
      ? setPrice(({ minPrice }) => ({ maxPrice: value, minPrice }))
      : setPrice(({ maxPrice }) => ({ minPrice: value, maxPrice }));
  }, []);
  console.log(processingProd);
  const FormSubmit = event => {
    if (checkInput.checkPrice) setCheckInput({ checkPrice: false });
    const checkPrice =
      price.minPrice === "" && price.minPrice === ""
        ? "initial values"
        : +price.maxPrice >= +price.minPrice &&
          price.minPrice !== "" &&
          !Number.isNaN(+price.maxPrice) &&
          !Number.isNaN(+price.minPrice);
    const checkSold = sold === "" ? "initial values" : !Number.isNaN(+sold);

    if (!checkPrice || !checkSold) {
      setCheckInput({ checkPrice: !checkPrice, checkSold: !checkSold });
      return false;
    }

    const x = arrProd.filter(prod => {
      const filterPrice =
        checkPrice === "initial values"
          ? true
          : +prod.price > +price.minPrice && +prod.price < +price.maxPrice;
      const filterSold =
        checkSold === "initial values" ? true : +sold >= +prod.sold;

      return filterPrice && filterSold;
    });
    setProcessingProd(x);
    event.preventDefault();
  };

  return (
    <Fragment>
      <form onSubmit={FormSubmit}>
        {checkInput.checkPrice && (
          <div>{"Please provide a valid price range"}</div>
        )}
        {"Min"}
        <input
          type={"text"}
          name={"minPrice"}
          size={6}
          maxLength={10}
          value={price.minPrice}
          onChange={PriceMaxMin}
        />
        {"Max"}
        <input
          type={"text"}
          name={"maxPrice"}
          size={6}
          maxLength={10}
          value={price.maxPrice}
          onChange={PriceMaxMin}
        />
        {checkInput.checkSold && (
          <div>{"Please provide a valid price range"}</div>
        )}
        {"Sold"}
        <input
          type={"text"}
          name={"minPrice"}
          size={6}
          maxLength={10}
          value={sold}
          onChange={({ target: { value, name } }) => setSold(value)}
        />
        <input type="submit" title={"Submit price range"} value={"Go"} />
      </form>
    </Fragment>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
4b9b3361

Ответ 1

После прочтения вашего вопроса я не был уверен, но я предполагаю, что вы имеете в виду, как checkPrice === "initial values" и checkSold === "initial values" неоднократно проверяются в этом фильтре:

const x = arrProd.filter(prod => {
  const filterPrice =
    checkPrice === "initial values"
      ? true
      : +prod.price > +price.minPrice && +prod.price < +price.maxPrice;
  const filterSold =
    checkSold === "initial values" ? true : +sold >= +prod.sold;

  return filterPrice && filterSold;
});

Действительно, этого должно быть достаточно, чтобы протестировать это только один раз. Так что давайте перенесем весь тест за пределы фильтра.

const x = arrProd.filter(
    checkPrice === "initial values"
        ? checkSold === "initial values"
            ? prod => true
            : prod => +sold >= +prod.sold
        : checkSold === "initial values"
            ? prod => +prod.price > +price.minPrice && +prod.price < +price.maxPrice
            : prod => +prod.price > +price.minPrice && +prod.price < +price.maxPrice && +sold >= +prod.sold
);

Обратите внимание, что теперь у нас есть четыре отдельных предиката. Между ними есть дублирование кода. Это можно устранить с помощью именованных функций.

const acceptAny = prod => true;
const acceptIfPriceInRange = prod => +prod.price > +price.minPrice && +prod.price < +price.maxPrice;
const acceptIfSoldInRange = prod => +sold >= +prod.sold;
const acceptIfBothInRange = prod => acceptIfPriceInRange(prod) && acceptIfSoldInRange(prod);

const x = arrProd.filter(
    checkPrice === "initial values"
        ? checkSold === "initial values" ? acceptAny : acceptIfSoldInRange
        : checkSold === "initial values" ? acceptIfPriceInRange : acceptIfBothInRange
);

Полный исходный файл:

import React, { Fragment, useCallback, useState } from "react";
import ReactDOM from "react-dom";

const arrProd = [
  {
    price: "5.75",
    sold: "100"
  },
  {
    price: "2.36",
    sold: "15"
  },
  {
    price: "5.48",
    sold: "20"
  },
  {
    price: "4.49",
    sold: "200"
  },
  {
    price: "3.15",
    sold: "258"
  },
  {
    price: "9.99",
    sold: "479"
  },
  {
    price: "4.8",
    sold: "147"
  },
  {
    price: "8",
    sold: "951"
  },
  {
    price: "4.27",
    sold: "753"
  },
  {
    price: "2.46",
    sold: "852"
  },
  {
    price: "4.99",
    sold: "742"
  },
  {
    price: "3.49",
    sold: "10"
  },
  {
    price: "2",
    sold: "26"
  },
  {
    price: "3.83",
    sold: "39"
  },
  {
    price: "9.98",
    sold: "47"
  },
  {
    price: "6.77",
    sold: "96"
  }
];

function App() {
  const [price, setPrice] = useState({ maxPrice: "", minPrice: "" });
  const [sold, setSold] = useState("");
  const [processingProd, setProcessingProd] = useState([]);
  const [checkInput, setCheckInput] = useState({
    checkPrice: false,
    checkSold: false
  });

  const PriceMaxMin = useCallback(({ target: { value, name } }) => {
    name === "maxPrice"
      ? setPrice(({ minPrice }) => ({ maxPrice: value, minPrice }))
      : setPrice(({ maxPrice }) => ({ minPrice: value, maxPrice }));
  }, []);
  console.log(processingProd);
  const FormSubmit = event => {
    if (checkInput.checkPrice) setCheckInput({ checkPrice: false });
    const checkPrice =
      price.minPrice === "" && price.minPrice === ""
        ? "initial values"
        : +price.maxPrice >= +price.minPrice &&
          price.minPrice !== "" &&
          !Number.isNaN(+price.maxPrice) &&
          !Number.isNaN(+price.minPrice);
    const checkSold = sold === "" ? "initial values" : !Number.isNaN(+sold);

    if (!checkPrice || !checkSold) {
      setCheckInput({ checkPrice: !checkPrice, checkSold: !checkSold });
      return false;
    }

    const acceptAny = prod => true;
    const acceptIfPriceInRange = prod => +prod.price > +price.minPrice && +prod.price < +price.maxPrice;
    const acceptIfSoldInRange = prod => +sold >= +prod.sold;
    const acceptIfBothInRange = prod => acceptIfPriceInRange(prod) && acceptIfSoldInRange(prod);

    const x = arrProd.filter(
        checkPrice === "initial values"
            ? checkSold === "initial values" ? acceptAny : acceptIfSoldInRange
            : checkSold === "initial values" ? acceptIfPriceInRange : acceptIfBothInRange
    );

    setProcessingProd(x);
    event.preventDefault();
  };

  return (
    <Fragment>
      <form onSubmit={FormSubmit}>
        {checkInput.checkPrice && (
          <div>{"Please provide a valid price range"}</div>
        )}
        {"Min"}
        <input
          type={"text"}
          name={"minPrice"}
          size={6}
          maxLength={10}
          value={price.minPrice}
          onChange={PriceMaxMin}
        />
        {"Max"}
        <input
          type={"text"}
          name={"maxPrice"}
          size={6}
          maxLength={10}
          value={price.maxPrice}
          onChange={PriceMaxMin}
        />
        {checkInput.checkSold && (
          <div>{"Please provide a valid price range"}</div>
        )}
        {"Sold"}
        <input
          type={"text"}
          name={"minPrice"}
          size={6}
          maxLength={10}
          value={sold}
          onChange={({ target: { value, name } }) => setSold(value)}
        />
        <input type="submit" title={"Submit price range"} value={"Go"} />
      </form>
    </Fragment>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Отказ от ответственности: я не тестировал полный код; Я оставлю это на ваше усмотрение.