У меня есть группа строк в Javascript, и мне нужно написать функцию, которая определяет, принадлежит ли другая конкретная строка к этой группе или нет.
Как быстрее всего этого добиться? Можно ли поместить группу значений в массив, а затем написать функцию, которая просматривает массив?
Я думаю, что если я сохраню значения отсортированными и выполню двоичный поиск, он должен работать достаточно быстро. Или есть какой-нибудь другой умный способ сделать это, который может работать быстрее?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Использование хеш-таблицы может быть более быстрым вариантом.
Какой бы вариант вы ни выбрали, его определенно стоит протестировать на фоне рассмотренных вами альтернатив.
Вы можете использовать такой объект:
// prepare a mock-up object
setOfValues = {};
for (var i = 0; i < 100; i++)
setOfValues["example value " + i] = true;
// check for existence
if (setOfValues["example value 99"]); // true
if (setOfValues["example value 101"]); // undefined, essentially: false
При этом используется тот факт, что объекты реализованы в виде ассоциативных массивов. Насколько это быстро, зависит от ваших данных и реализации движка JavaScript, но вы можете легко провести некоторое тестирование производительности, чтобы сравнить его с другими вариантами выполнения.
Если значение может встречаться в вашем наборе более одного раза и для вас важно «как часто», вы также можете использовать увеличивающееся число вместо логического, которое я использовал в моем примере.
Будет оценено как undefined. Это не приведет к ошибке. Попробуйте сами.
Зависит от того, сколько там ценностей.
Если есть несколько значений (от 10 до 50), поиск в массиве может быть нормальным. Хеш-таблица может быть излишней.
Если у вас много значений, хеш-таблица - лучший вариант. Это требует меньше работы, чем сортировка значений и выполнение двоичного поиска.
Я думал, что все в JS было хеш-таблицей, массив - это просто 0 => первое, 1 => второе, не так ли?
@Trull: Я в этом сомневаюсь. Array отличается от Object и, вероятно, оптимизирован для производительности, хотя это будет зависеть от реализации.
Используйте хеш-таблицу и сделайте следующее:
// Initialise the set
mySet = {};
// Add to the set
mySet["some string value"] = true;
...
// Test if a value is in the set:
if (testValue in mySet) {
alert(testValue + " is in the set");
} else {
alert(testValue + " is not in the set");
}
Использование оператора «in», вероятно, является более элегантным способом сделать это. +1
Пытаясь танцевать вокруг AngularJS 'ng-if, я придумал такой синтаксис (сразу после прочтения этого ответа): ({value1: 1, value2: 1})[ 'value2' ] - автономный тест карты.
Комментарий к упомянутым выше хеш-решениям. Фактически {} создает объект (также упомянутый выше), который может привести к некоторым побочным эффектам. Одна из них заключается в том, что ваш «хэш» уже предварительно заполнен методами объекта по умолчанию.
Итак, "toString" in setOfValues будет true (по крайней мере, в Firefox).
Вы можете добавить еще один символ, например "." к вашим строкам, чтобы обойти эту проблему, или используйте объект Hash, предоставленный библиотекой «prototype».
Спасибо, что заметили это. Еще одна причина ненавидеть JavaScript.
Возможный способ, особенно эффективный, если набор неизменяем, но все еще можно использовать с набором переменных:
var haystack = "monday tuesday wednesday thursday friday saturday sunday";
var needle = "Friday";
if (haystack.indexOf(needle.toLowerCase()) >= 0) alert("Found!");
Конечно, вам может потребоваться изменить разделитель в зависимости от строк, которые вы должны туда поместить ...
Более надежный вариант может включать границы, гарантирующие, что ни «день свадьбы», ни «день» не могут совпадать положительно:
var haystack = "!monday!tuesday!wednesday!thursday!friday!saturday!sunday!";
var needle = "Friday";
if (haystack.indexOf('!' + needle.toLowerCase() + '!') >= 0) alert("Found!");
Может не понадобиться, если ввод является уверенным (например, вне базы данных и т. д.).
Я использовал это в скрипте Greasemonkey, с преимуществом использования стога сена непосредственно из хранилища GM.
Наткнулся на это и понял, что ответы устарели. В наши дни вы не должны реализовывать наборы с использованием хэш-таблиц, за исключением крайних случаев. Вы должны использовать наборы.
Например:
> let set = new Set();
> set.add('red')
> set.has('red')
true
> set.delete('red')
true
> set.has('red')
false
Обратитесь к этому сообщению SO для получения дополнительных примеров и обсуждения: Способы создания набора в JavaScript?
Я знаю, что это старый пост. Но чтобы определить, находится ли значение в наборе значений, мы можем манипулировать с помощью массива indexOf(), который ищет и определяет настоящее значения.
var myString = "this is my large string set";
var myStr=myString.split(' ');
console.info('myStr contains "my" = '+ (myStr.indexOf('my')>=0));
console.info('myStr contains "your" = '+ (myStr.indexOf('your')>=0));
console.info('integer example : [1, 2, 5, 3] contains 5 = '+ ([1, 2, 5, 3].indexOf(5)>=0));Можно использовать ES6 включает в себя.
var string = "The quick brown fox jumps over the lazy dog.",
substring = "lazy dog";
console.info(string.includes(substring));
Это не работает. setOfValues [x], где x отсутствует в наборе, не будет оцениваться как undefined, это вызовет ошибку. Вы хотите: «x in setOfValues» для проверки членства.