Как создать, если условный оператор из строки в JavaScript для цикла без использования eval () - PullRequest
0 голосов
/ 11 февраля 2019

Я пытаюсь создать функцию расширенного поиска для использования в многомерном массиве объектов товара.В форме пользователь будет иметь возможность сузить результаты продукта на основе данных в нескольких различных атрибутах (например, «цена» <20 && «страна» == «Франция»), регион == «Нью-Йорк» &&'vintage' == '2016' && 'qty> 20 ").Данные в переменной data форматируются следующим образом:

    0:
        name: "Kedem Cream Red Concord"
        appellation: "New York"
        country: "United States"
        price: "10.99"
        primarygrape: "Concord"
        qty: "1"

        region: "New York"
        regprice: "10.99"
        sku: "230"
        vintage: "NV"
    1:
        name: "Kendall Jackson Vintner's Chardonnay"

        appellation: ""

        country: "United States"

        price: "14.99"

        primarygrape: "Chardonnay"
        qty: "35"

        region: "California"

        regprice: "18.99"
        sku: "345"

        vintage: "2016"
... continuing on over 10,000 product records

Я подумал, что могу довольно легко создать строку на основе ввода в пользовательскую форму, которая суммирует то, что они ищут.Однако мне нужен безопасный способ оценки этой строки в моей функции, которая возвращает отфильтрованные результаты в resultsArray

Я смог заставить ее работать с функцией eval(), но я знаю, что это небезопасноили эффективный.Я также пытался дурачиться с помещением условий в массив и пытаться включить это в цикл for, но я не мог понять, как заставить это работать.Сложность в том, что условия могут быть любым количеством вещей, включающих следующие атрибуты продукта: наименование, страна, цена, основной сорт, кол-во, регион, винтаж .И разные атрибуты используют разные операторы (например, страна, регион и другие используют '==', а кол-во и цена используют '>' или '<'). </p>

Этот код работает, но использует табу eval()function:

var conditional = "data[i].price < 20 && data[i].country == 'France' && data[i].vintage == '2016'";

var resultArray = [];
console.log(data.length);
for (var i = 0; i < data.length; i++)
{
    if (eval(conditional))
        {
            resultArray.push(data[i]);
        }
    }
}

Это не работает, так как приводит к ошибке Uncaught ReferenceError: data is not defined:

var conditional = "return data[i].price < 20 && data[i].country == 'France' && data[i].vintage == '2016'";

var resultArray = [];
console.log(data.length);
for (var i = 0; i < data.length; i++)
{
    if (new Function(conditional)())
        {
            resultArray.push(data[i]);
        }
    }
}

Любая идея, как динамически создать это условное выражение if, чтобы оно распозналопеременная data?Или есть лучшее решение?

Ответы [ 2 ]

0 голосов
/ 11 февраля 2019

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

Например, у вас есть массив с числами:

var arr = [1,3,6,2,6]

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

Теперь законченный пример для фильтрации всех четных чисел:

arr.filter(function(element) {return element%2 == 0})

Надеюсь, вам этого хватит, чтобы продолжить.:-) В следующем фрагменте я сделал небольшой пример с вашим массивом данных

 var your_data_array = [
 { 
       name: "Kendall Jackson Vintner's Chardonnay",
        appellation: "",
        country: "United States",
        price: "14.99",
        primarygrape: "Chardonnay",
        qty: "35",
        region: "California",
        regprice: "18.99",
        sku: "345",
        vintage: "2016" },
        { 
       name: "Kendall Jackson Vintner's Chardonnay",
        appellation: "",
        country: "United States",
        price: "14.99",
        primarygrape: "Chardonnay",
        qty: "35",
        region: "California",
        regprice: "18.99",
        sku: "345",
        vintage: "2016" },
        { 
       name: "Kendall Jackson Vintner's Chardonnay",
        appellation: "",
        country: "United States",
        price: "14.99",
        primarygrape: "Chardonnay",
        qty: "35",
        region: "California",
        regprice: "18.99",
        sku: "345",
        vintage: "2016" }
 ]
 
 var filtered_array = your_data_array.filter(function(dataElement) {
   return dataElement.country == "United States";
 })
 
 console.log(filtered_array)
0 голосов
/ 11 февраля 2019

Если вы получаете условия, основанные на пользовательском вводе, вы можете отформатировать его так, как вам нравится, это не обязательно должна быть строка.Я бы порекомендовал массив, который выглядит примерно так:

var conditions = [
  {
    property: 'price',
    comparator: '<',
    value: 20
  },
  {
    property: 'country',
    comparator: '=',
    value: 'France'
  }
];

Затем вы можете использовать метод filter для генерации массива результатов:

var resultArray = data.filter(function(item) {
  for (var i = 0; i < conditions.length; i++) {
    if (conditions[i].comparator === '=' && 
        item[conditions[i].property] !== conditions[i].value) {
      return false;
    }

    if (conditions[i].comparator === '>' && 
        item[conditions[i].property] <= conditions[i].value) {
      return false;
    }

   if (conditions[i].comparator === '<' && 
        item[conditions[i].property] >= conditions[i].value) {
      return false;
    }
  }
})
...