Javascript: как вернуть значения из массива хэшей, если значение находится в пределах диапазона

Изучающий Javascript здесь.

Проблема: У меня есть список шестнадцатеричных диапазонов, и мне нужно вернуть значение, если значение запроса находится в пределах диапазона. Данные выглядят так:

[
  {...},
  {"start": 0x3C0000, "end": 0x3FFFFF, "country": "Germany"},
  {"start": 0x044000, "end": 0x044FFF, "country": "Ghana"},
  {...}
]

У меня есть шестнадцатеричное значение, и я хотел бы получить страну, если шестнадцатеричное значение находится между началом и концом.

Вопрос 1: Каким будет наиболее эффективный способ вернуть страну, если запрос находится между началом и концом?

Вопрос 2: Будет ли более разумный способ форматирования данных, который позволит выполнять более быстрый/эффективный запрос?

Цель моих вопросов — изучить альтернативы перебору массива с помощью цикла.

Какой "запрос"? Пожалуйста, добавьте несколько примеров входных данных и ожидаемых результатов ... И в зависимости от того, сколько элементов в вашем списке, оптимизация может даже не стоить усилий.

derpirscher 31.03.2023 09:43

Ваш набор данных должен быть довольно большим, прежде чем производительность / «эффективность» различных подходов действительно начнет иметь значение. Учитывая, что в мире 195 стран, я сомневаюсь, что дело обстоит именно так. «Цель моих вопросов — изучить альтернативы перебору массива с помощью цикла». - затем ознакомьтесь с методами массива, такими как developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

CBroe 31.03.2023 09:47

array.find(x => и проверьте, находится ли запрос между x.start и x.end

cmgchess 31.03.2023 09:47

Простым способом оптимизации может быть сортировка массива по свойству start. Затем вы можете выполнить бинарный поиск в списке. Или вы можете создать дерево поиска

derpirscher 31.03.2023 09:53

@derpirscher: Вы правы, объяснение как-то исчезло, когда я написал вопрос. Вероятно, случайно нажал Shift при редактировании или что-то в этом роде. Добавил объяснение сейчас.

Stefan Gofferje 31.03.2023 11:29
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
5
58
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Обычный цикл for, вероятно, будет наиболее эффективным методом.

При этом есть элегантное решение с filter и map.

let res = array.filter(o => x.start <= query && query <= x.end).map(o => o.country);

Конечно, если вам нужен только один результат, используйте вместо него Array#find.

let res = array.find(o => x.start <= query && query <= x.end)?.country;

почему цикл for быстрее фильтра. это потому что карта тогда не нужна?

cmgchess 31.03.2023 09:49

@cmgchess В общем, с обычным циклом for меньше накладных расходов. Вы можете посмотреть на них: stackoverflow.com/questions/53072292/… , stackoverflow.com/questions/31459395/…

Unmitigated 31.03.2023 09:51

@cmgchess Потому что с filter или find всегда придется вызывать дополнительную функцию (то есть обратный вызов) для каждого элемента, что создает некоторые накладные расходы.

derpirscher 31.03.2023 09:58

Спасибо @Unmitigated! За решение и особенно за ссылки! Для новичка было довольно интересно читать!

Stefan Gofferje 31.03.2023 11:36

Мы не можем сделать за O(n), если диапазон не отсортирован. Но для последующих операций мы можем сделать за O(log(n)), учитывая, что конечные точки диапазона можно расположить на числовой прямой без какой-либо внутренней фрагментации. (т.е. [2,3], [5,6] содержит внутреннюю фрагментацию, а [2,3],[3,4] — нет).

Итак, давайте возьмем рассматриваемые значения диапазона в виде {{x1,y1,v1},{x2,y2,v2}...{xn,yn,vn}} и предположим, что он отсортирован. Если это невозможно, вы можете предположить, что можете, и считать, что оно имеет какое-то нулевое значение. Таким образом, мы получаем диапазон в числовой строке как [x1,y1,x2,y2,x3,y3....xn,yn] для нашего примера, где y1<=x2,y2<=x3 (другие сравнения тривиальны, так как это конечные точки диапазона).

Теперь создайте массив, содержащий значения конечных точек диапазона. Вы можете использовать либо 1-ю конечную точку, либо последнюю конечную точку диапазона. Для нашего примера возьмем первую конечную точку. 0-й индекс соответствует v1, 1-й — null (в диапазоне [y1,x2] нет значения, как упоминалось ранее). Здесь мы используем стандартный модуль bisect Python для эффективной индексации. Подайте диапазон точек останова (для нашего примера это x1,y1,x2,y2 .. xn,yn) с вашим значением запроса (возьмем xi). (Вы можете применить ту же логику в js)

import bisect as bst

breakpoint = [x1,y1,x2,y2,x3,y3...xn,yn]
query = xi
rangeValueMap = [v1,null,v2,null...]

value = bst.bisect(breakpoint,query)

if value==null:
 print("No range covers the value {0}".format(query))
else:
 print("Value is %d"%(value))
 

Используйте индекс, возвращенный из bisect, чтобы получить значение из уже созданного массива. Если это null , то диапазон не существует, иначе он существует и использует значение.

Другие вопросы по теме