==
выполняет контрольную проверку равенства, ссылаясь на то, что 2 объекта (строки в этом случае) относятся к одному и тому же объекту в памяти.
Метод equals()
будет проверять, будет ли содержимое или состояния двух объектов одинаковы.
Очевидно, что ==
работает быстрее, но во многих случаях может (может) давать ложные результаты, если вы просто хотите сказать, имеет ли 2 String
s тот же текст.
Определенно рекомендуется использовать метод equals()
.
Не беспокойтесь о производительности. Некоторые способы поощрения использования String.equals()
:
String.equals()
сначала проверяет ссылочное равенство (используя ==
), и если две строки одинаковы по ссылке, дальнейший расчет Выполняется! String.equals()
будет проверять длину строк. Это также является быстрой операцией, поскольку класс String
хранит длину строки, не нужно считать символы или кодовые точки. Если длины отличаются, дальнейшая проверка не выполняется, мы знаем, что они не могут быть равными. Когда все сказано и даже если у нас есть гарантия, что строки являются стажерами, использование метода equals()
все еще не является издержками, которые можно было бы подумать, определенно рекомендуемым способом. Если вам нужна эффективная проверка ссылок, используйте перечисления, где гарантируется спецификацией и реализацией языка, что одно и то же значение перечисления будет одним и тем же объектом (по ссылке).
Я построил алгоритм следующим образом:
function omitNodeWithName(tree, name) {
if (tree.name === name) return undefined;
const children = tree.children.map(child => omitNodeWithName(child, name))
.filter(node => !!node);
return {
...tree,
children
}
}
Вы можете использовать его для возврата нового дерева без элемента:
noHydrogen = omitNodeWithName(tree, "Hydrogen")
Если вы не возражаете против изменения дерева параметров на месте , это должно сработать. Обратите внимание, что он вернет null
, если вы попытаетесь удалить корень.
const tree = { id: 1, name: "Dog", parent_id: null, children: [ { id: 2, name: "Food", parent_id: 1, children: [] }, { id: 3, name: "Water", parent_id: 1, children: [ { id: 4, name: "Bowl", parent_id: 3, children: [] }, { id: 5, name: "Oxygen", parent_id: 3, children: [] }, { id: 6, name: "Hydrogen", parent_id: 3, children: [] } ] } ] };
const removeFromTree = (root, nameToDelete, parent, idx) => {
if (root.name === nameToDelete) {
if (parent) {
parent.children.splice(idx, 1);
}
else return null;
}
for (const [i, e] of root.children.entries()) {
removeFromTree(e, nameToDelete, root, i);
}
return tree;
};
console.log(removeFromTree(tree, "Oxygen"));
Ваш текущий код находится на правильном пути. Однако:
newTree = curNode.children.slice(index, index + 1);
выдвигает на первый план несколько проблем: нам нужно манипулировать массивом children
родителя, чтобы удалить curNode
вместо собственного children
массива [116]. Я передаю родительские объекты и дочерний индекс рекурсивно через вызовы, избавляя от проблем линейной операции findIndex
.
Кроме того, разрезание от index
до index + 1
извлекает только один элемент и не изменяет curNode.children
. Не очевидно, как использовать newArray
или возвращать его через стек вызовов. splice
кажется более подходящим инструментом для решения поставленной задачи: извлечение одного элемента на месте.
Обратите внимание, что эта функция удалит несколько записей, соответствующих nameToDelete
.
Мне нравится ответ @ VictorNascimento, но, применяя map
, затем filter
, каждый список children
будет повторяться дважды. Вот альтернатива с reduce
, чтобы избежать этого:
function removeFromTree(node, name) {
return node.name == name
? undefined
: {
...node,
children: node.children.reduce(
(children, child) => children.concat(removeFromTree (child, name) || []), [])
}
}
В случае, если вам нужен способ удаления элементов на месте, как предложил @ggorlen, я бы порекомендовал следующее решение, которое На мой взгляд проще:
function removeFromTree(node, name) {
if (node.name == name) {
node = undefined
} else {
node.children.forEach((child, id) => {
if (!removeFromTree(child, name)) node.children.splice(id, 1)
})
}
return node
}
Если можно использовать Lodash + Deepdash , то:
let cleaned = _.filterDeep([tree],(item)=>item.name!='Hydrogen',{tree:true});
Вот Codepen