#javascript #arrays #object #big-o
Вопрос:
У меня есть небольшое приложение, в котором у меня есть массив объектов. Каждый объект является учащимся, и каждый объект учащегося имеет массив тегов, который выглядит следующим образом:
const students =
[ { name: "John", tags: [ 'tag1', 'tag2' ] }
, { name: "Leslie", tags: [ 'tag1' ] }
, { name: "Mark", tags: [ 'tag', 'tag2' ] }
]
Прямо сейчас, чтобы найти студентов с одинаковыми тегами, я перебираю массив объектов и массив тегов для каждого студента, который равен O(n) в квадрате.
const filterByTag = (filter) => {
let result = [];
initialStudents.map((student) => {
student.tags.map((tag) => {
if (tag.includes(filter)) {
result.push(student);
}
});
});
return resu<
};
Как я могу уменьшить временную сложность? Я думал о создании объекта с тегами name ->, а затем просмотреть его, но, похоже, это тот же O(n) в квадрате.
Комментарии:
1. Вы почти всегда можете уменьшить временную сложность, используя карту ключей/значений/словарь для поиска. Кроме того, не используйте
map
asforEach
.2. Я пытался, но, похоже, мне придется пройти через каждое значение ключа и через каждое значение (массив), и в любом случае это O(n) в квадрате
3. Взгляните на структуру данных Trie или «Дерево префиксов», чтобы создать индекс.
Ответ №1:
Я не думаю, что здесь можно добиться каких-либо значительных успехов с точки зрения сложности. Нет никакого способа обойти повторение
- каждый студент
- каждый тег внутри каждого ученика
- каждый символ внутри каждой строки тега (абстрагируется за
.includes
)
Это требует значительной вычислительной сложности, которую вы уже реализуете довольно разумно.
Но вы можете сделать код немного лучше и уменьшить немного ненужных накладных расходов. Не используйте .map
для побочных эффектов-для побочных эффектов, используйте forEach
или for..of
. Но лучший подход здесь состоял бы в том, чтобы использовать .filter
для построения нового массива объектов учащихся в зависимости от того, какие из них проходят тест, поскольку вы, вероятно, хотите отправить только одного учащегося, когда он соответствует, а не этого учащегося для каждого соответствующего тега.
const filterByTag = (filter) => {
return initialStudents.filter(student =>
student.tags.some(
tag => tag.includes(filter)
)
);
};
(Используйте только .map
, когда вы используете результат вызова в качестве нового массива — например const mappedArray = originalArray.map(...
)