Показать сообщение отдельно
  #48 (permalink)  
Старый 29.01.2019, 14:32
Аватар для Malleys
Профессор
Отправить личное сообщение для Malleys Посмотреть профиль Найти все сообщения от Malleys
 
Регистрация: 20.12.2009
Сообщений: 1,714

Описание на данный момент занимает 351КБ места (то, которое у вас), и в основном содержит повторяющиеся HTML-элементы. Храните только сами данные, без того, как они должны быть представлены. Данные в чистом виде легко обрабатывать, чем пытаться их вытащить из разметки! (jQuery с этим ужасно не справляется, для этого лучше подходит класс DOMParser, он для такого и предназначен)

Но всё-таки вот вариант с DOMParser...
function fnSearch(array, pattern) {
	var parts = pattern.trim().toLowerCase().split(/\s+/);
	var p = new DOMParser();
	var s = Symbol.for("product description");
	
	return array.filter(function(product) {
		var description =
			s in product ?
			product[s] :
			product[s] =
				p	.parseFromString(product.html, "text/html")
					.body
					.textContent
					.toLowerCase()
					.split(/\s+/)
			;
		
		return parts.every(function(part) {
			return description.some(function(word) {
//					return word === part;
				return word.startsWith(part);
			});
		});
	});
}

Оно ищет так, чтобы каждое искомое слово в описании начиналось на него! Если вам нужно, что каждое искомое слово присутствовало полностью в описании, то используйте return word === part;. Я вам рекомендую использовать вариант (word.startsWith(part)), поскольку набрав только "nok" уже видно, что есть "nokia". Однако точное совпадение (word === part) предполагает, что пользователи полностью наберут "nokia", чтобы увидеть результаты "nokia". На самом же деле набрав только "nok", и увидев, что там ничего не появилось, пользователи скорей решат, что там нет того, о чём они думают, чем полностью будут вводить труднопроизносимые для них слова. Вариант (word.startsWith(part)) более интерактивный и подразумевает меньше усилии для достижения результата со стороны пользователя!

И ещё, если ничего не ввести, то (word === part) ничего не покажет, а (word.startsWith(part)) показывает всё! Поэтому вам нужна пошаговая *загрузка*, т. е., например показывайте первые 12 результатов, а остальные добавляются, например, при нажатии на кнопку в конце списка!

Если можно ничего не вводить и получать результаты, то можно добавить, например, ценовой фильтр. (Возможности безграничны!)

Сообщение от Alexko64
не возможно реализовать точный поиск
Вы можете комбинировать (word === part) и (word.startsWith(part)) и пусть пользователь сам выбирает, какой ему нужен поиск! (в примере ниже я показываю, как это сделать)

Также из вашего HTML можно извлечь чистые данные. Данные в чистом виде легко обрабатывать, чем пытаться их вытащить из разметки!
Получается 216КБ после замены на JSON без лишних пробелов и разметки (только чистые данные), что в свою очередь в за-gzip-ированном виде занимает 28КБ.

И уже на основе такого чистого JSON легко генерировать какую угодно разметку! Тогда не нужно использовать даже DOMParser!

Тогда эта функция поиска выглядит так...
function fnSearch(array, pattern) {
	var parts = pattern.trim().toLowerCase().split(/\s+/);

	return array.filter(function({ product }) {
		var description = product.toLowerCase().split(/\s+/);

		return parts.every(function(part) {
			return description.some(function(word) {
				// return word === part;
				return word.startsWith(part);
			});
		});
	});
}


Вот для примера перевёл ваши данные в чистый JSON, и написал маленькую функцию performSearch, которая запускает fnSearch и печатает результат...

Сам пример https://codesandbox.io/s/nnkw1q7rvm?view=preview и код в песочнице
<iframe src="https://codesandbox.io/embed/nnkw1q7rvm?view=preview" style="width:100%; height:700px; border:0; border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe>


Пользователи вам не роботы извергающие точные запросы! Так что они вам туда ещё напишут "айфон" и "xaomi", так что вы можете улучшить свою программу, добавив... (подсказка: транслитерация, расстояние Левенштейна)

Последний раз редактировалось Malleys, 29.01.2019 в 15:17.
Ответить с цитированием