#javascript #collections #set #sortedset
#javascript #Коллекции #набор #sortedset
Вопрос:
Я ищу сортированный контейнер для JavaScript.
Я использую C std::set
, https://en.cppreference.com/w/cpp/container/set и попробуйте перенести мой код на JavaScript.
Карта JavaScript не является упорядоченным контейнером. Мне нужен какой-то упорядоченный контейнер.
Мне не нужен полностью совместимый контейнер std::set
на C . Мои требования
- Поддержка пользовательских компараторов
- Автоматически сортируется
- Найдите конкретное значение. Если значение не найдено, получите следующее значение (значение позиции вставки).
- Операция увеличения / уменьшения итератора (переход к предыдущему / следующему элементу)
Вот пример кода на C , который демонстрирует мои требования: https://wandbox.org/permlink/wGnTvTPyOej4G9jo
#include <set>
#include <iostream>
int main() {
// 1. Custom comparator support
auto comp = [](auto lhs, auto rhs) { return lhs < rhs; };
std::set<int, decltype(comp)> s(comp);
// 2. Automatically sorted
s.insert(5);
s.insert(2);
s.insert(3);
for (auto v : s) std::cout << v << std::endl;
auto finder = [amp;](auto v) {
std::cout << "try find " << v << std::endl;
// 3. Find the specific value.
// If value is not found, get the next value (insertion position value).
auto it = s.lower_bound(v);
auto end = s.end();
if (it == end) {
std::cout << v << " not found. Insertion point is tail" << std::endl;
}
else {
if (*it == v) {
std::cout << v << " found" << std::endl;
if (it != s.begin()) {
auto left = it;
// 4. Iterator increment/decrement operation
--left;
std::cout << "prev elem is " << *left << std::endl;
}
if (it != --end) {
auto right = it;
// 4. Iterator increment/decrement operation
right;
std::cout << "next elem is " << *right << std::endl;
}
}
else {
std::cout << v << " not found. Insertion point is just before " << *it << std::endl;
}
}
};
finder(1);
finder(3);
}
Я нашел следующие контейнеры:
collctions/sorted-set
https://www.npmjs.com/package/sorted-btree
Она удовлетворяет требованиям 1, 2 и 3, но не поддерживает 4.
collctions/sorted-array-set
http://www.collectionsjs.com/sorted-array-set
Она удовлетворяет требованиям 1, 2 и 4 (возможно), но не поддерживает 3.
Кто-нибудь знает какой-нибудь контейнер, который поддерживает мои требования?
Комментарии:
1. Может быть, использовать простой массив JS и использовать такие функции, как BinarySearch / binaryInsert из библиотеки закрытия ( google.github.io/closure-library/api/goog . array.html )?
Ответ №1:
js-sdsl
Стандартная библиотека структуры данных javascript, которая сравнивается с C STL.
Эта библиотека имеет строгую гарантию сложности по времени и может использоваться с уверенностью.
Последняя бета-версия включает функции итератора, которые можно использовать как итератор в c .
Включенные структуры данных
- Вектор
- Стек
- Очередь
- Список ссылок
- Deque
- Приоритетная очередь
- Набор (с использованием RBTree)
- Карта (с использованием RBTree)
- HashSet (только для справки)
- HashMap (только для справки)
Использование
Чтобы помочь вам лучше использовать, мы предоставляем этот документ API.
Ответ №2:
collctions/sorted-array-set
http://www.collectionsjs.com/sorted-array-set
Она эффективно удовлетворяет следующим требованиям.
- Поддержка пользовательских компараторов. См. http://www.collectionsjs.com/sorted-set конструктор (в правом верхнем углу страницы).
- Автоматически сортируется. Это очевидно. Коллекция отсортирована-установлена.
- Найдите конкретное значение. Если значение не найдено, получите следующее значение (значение позиции вставки). Используйте
findLeastGreaterThanOrEqual(value)
http://www.collectionsjs.com/method/find-least-greater-than-or-equal Если вы хотите найти конкретное значение, и если значение не найдено, получите предыдущее значение, тогда вы можете использоватьfindGreatestLessThanOrEqual(value)
http://www.collectionsjs.com/method/find-greatest-less-than-or-equal Временная сложность равна O(logN).
Это неэффективно, но также удовлетворяет следующему требованию.
- Операция увеличения / уменьшения итератора (переход к предыдущему / следующему элементу). Для доступа к родственным элементам нет итераторов, но вы можете использовать
findLGreatestLessThan(value)
http://www.collectionsjs.com/method/find-greatest-less-than для доступа к предыдущему элементу и может использоватьfindLeastGreaterThan(value)
http://www.collectionsjs.com/method/find-least-greater-than чтобы получить доступ к следующему элементу. Поиск начинается с корневого элемента дерева. Таким образом, каждый раз для доступа к родственному элементу требуется O (logN) время сложности.