как использовать оператор if, когда свойство имеет значение null - PullRequest
0 голосов
/ 07 июня 2018

У меня есть простое утверждение, как показано.Однако рекурсивный оператор в конечном итоге не имеет значения val и вместо выполнения остальной части моего кода Windows PowerShell просто существует с TypeError: Невозможно прочитать свойство 'val' из null.

chkL = (L) => {
    if(L.left.val) chkL(L.left);
}

Вотполный код:

function TreeNode(val) {
    this.val = val;
    this.left = this.right = null;
}

let tree1 = new TreeNode(1);
tree1.left = new TreeNode(3);
tree1.right = new TreeNode(2);
tree1.left.left = new TreeNode(5);

let tree2 = new TreeNode(2);
tree2.left = new TreeNode(1);
tree2.right = new TreeNode(3);
tree2.left.right = new TreeNode(4);
tree2.right.right = new TreeNode(7);

var mergeTrees = function(t1, t2) {
    let ans = Object.assign({}, t1);

    chkL = (L) => {
        if(L.left.val) chkL(L.left);
    }

    if(t1.left.val) {
        chkL(t1.left);
    }


};

mergeTrees(tree1, tree2);

Мне интересно, есть ли способ, как я могу использовать что-то вроде eval () или попробовать catch в операторе if, чтобы остановить разрыв сценария?Обратите внимание, я знаю, что могу просто удалить часть .val логики, однако мне интересно только, как выполнить код, подобный этому.

Ответы [ 4 ]

0 голосов
/ 08 июня 2018

рекурсия является функциональной

Рекурсия является функциональным наследием, и поэтому написание вашей программы в функциональном стиле даст наилучшие результаты.Это означает, что нужно избегать мутаций, нулевых проверок и других побочных эффектов.Вместо того, чтобы убивать ваш код, я просто надеюсь, что другая программа прояснит, что есть более эффективные способы решения этой проблемы ...

Мы начинаем с Empty и Node

const Empty =
  {}

const Node = (value, left = Empty, right = Empty) =>
  ({ value, left, right })

И путь к merge двум узлам

const merge = (n1, n2) =>
  n1 === Empty
    ? n2

  : n2 === Empty
    ? n1

  : Node ( n1.value + n2.value // some merging operation!
         , merge (n1.left, n2.left)
         , merge (n1.right, n2.right)
         )

Теперь мы возьмем два дерева, t1 и t2

const t1 =
  Node ('A'
       , Node ('B')
       , Node ('C', Node ('D'), Node ('E'))
       )

const t2 =
  Node ('a'
       , Node ('b', Node ('x'))
       , Node ('c'
              , Node ('d', Node ('y'))
              )
       )

Чтобы увидеть, что происходитдалее, мы добавляем некоторую функцию к print деревьям

const print = (node, pre = '', child = '') =>
  node === Empty
    ? ""
    : print (node.left, child + '┌── ', child + '.   ')
      + pre + String (node.value) + '\n'
      + print (node.right, child + '└── ', child + '.   ')

console.log (print (t1)
// ┌── B
// A
// .   ┌── D
// └── C
// .   └── E

console.log (print (t2))
// .   ┌── x
// ┌── b
// a
// .   .   ┌── y
// .   ┌── d
// └── c

Теперь для празднования - обратите внимание, что ни t1, ни t2 не изменяются в результате вызова merge.Совершенно новый t3 сформирован.

const t3 =
  merge (t1, t2)

console.log (print (t3))
// .   ┌── x
// ┌── Bb
// Aa
// .   .   ┌── y
// .   ┌── Dd
// └── Cc
// .   └── E

Запустите полную программу в вашем браузере ниже

const Empty =
  {}

const Node = (value, left = Empty, right = Empty) =>
  ({ value, left, right })
  
const merge = (n1, n2) =>
  n1 === Empty
    ? n2
  
  : n2 === Empty
    ? n1
    
  : Node ( n1.value + n2.value // some merging function!
         , merge (n1.left, n2.left)
         , merge (n1.right, n2.right)
         )

const print = (node, pre = '', child = '') =>
  node === Empty
    ? ""
    : print (node.left, child + '┌── ', child + '.   ')
      + pre + String (node.value) + '\n'
      + print (node.right, child + '└── ', child + '.   ')

const t1 =
  Node ('A'
       , Node ('B')
       , Node ('C', Node ('D'), Node ('E'))
       )
       
const t2 =
  Node ('a'
       , Node ('b', Node ('x'))
       , Node ('c'
              , Node ('d', Node ('y'))
              )
       )
       
console.log (print (t1))
// ┌── B
// A
// .   ┌── D
// └── C
// .   └── E

console.log (print (t2))
// .   ┌── x
// ┌── b
// a
// .   .   ┌── y
// .   ┌── d
// └── c

const t3 =
  merge (t1, t2)

console.log (print (t3))
// .   ┌── x
// ┌── Bb
// Aa
// .   .   ┌── y
// .   ┌── Dd
// └── Cc
// .   └── E

функциональные средства гибкие

Очевидные улучшения этой программы включают в себя превращение merge в функцию более высокого порядка, такую ​​что + не жестко запрограммирован в нашей программе

// improved merge; user-defined merging function, f
const merge = (<b>f,</b> n1, n2) =>
  n1 === Empty
    ? n2

  : n2 === Empty
    ? n1

  : Node ( <b>f (</b>n1.value, n2.value<b>)</b> // <---
         , merge (<b>f,</b> n1.left, n2.left)
         , merge (<b>f,</b> n1.right, n2.right)
         )

Теперь вызывающая сторона merge может определить, как объединяются значения.В этом примере мы помещаем оба значения в массив

const t4 =
  merge (<b>(v1,v2) => [v1, v2],</b> t1, t2)

console.log (print (t4))
// .   ┌── x
// ┌── B,b
// A,a
// .   .   ┌── y
// .   ┌── D,d
// └── C,c
// .   └── E

Теперь, когда мы print дерева, массивы преобразуются в строки.Другим очевидным улучшением здесь было бы настроить нашу print функцию, аналогичную той, которую мы сделали с merge, позволяя пользователю указать способ печати значений

// improved print; String is no longer hard-coded
const print = (node, <b>fmt = String,</b> pre = '', child = '') =>
  node === Empty
    ? ""
    : print (node.left, <b>fmt,</b> child + '┌── ', child + '.   ')
      + pre + <b>fmt</b> (node.value) + '\n' // <---
      + print (node.right, <b>fmt,</b> child + '└── ', child + '.   ')

Теперь мы можемукажите нашу функцию форматирования в качестве второго аргумента

console.log (print (t4<b>, JSON.stringify</b>)) // print as JSON!
// .   ┌── "x"
// ┌── ["B","b"]
// ["A","a"]
// .   .   ┌── "y"
// .   ┌── ["D","d"]
// └── ["C","c"]
// .   └── "E"

В деревьях выше мы выводим "" для Empty узлов.Возможно, нам нужен способ их визуализации, чтобы мы могли изменить функцию print еще раз

// improved print; displays Empty nodes as ∅
const print = (node, fmt = String, pre = '', child = '') =>
  node === Empty
    ? <b>pre + '\u2205\n'</b> // <---
    : print (node.left, fmt, child + '┌── ', child + '.   ')
      + pre + fmt (node.value) + '\n'
      + print (node.right, fmt, child + '└── ', child + '.   ')

console.log (print (t3))
// .   .   ┌── ∅
// .   ┌── x
// .   .   └── ∅
// ┌── Bb
// .   └── ∅
// Aa
// .   .   .   ┌── ∅
// .   .   ┌── y
// .   .   .   └── ∅
// .   ┌── Dd
// .   .   └── ∅
// └── Cc
// .   .   ┌── ∅
// .   └── E
// .   .   └── ∅
0 голосов
/ 07 июня 2018

Использование ES6 для деструктуризации:

const chkL = ({ left, left: { val } = {} }) => {
    if (val) {
        chkL(left);
    }
    // the invisible last line in all JS functions
    return undefined;
}

Теперь эта функция может быть написана гораздо проще, чем та же:

const chkL = () => undefined;
0 голосов
/ 07 июня 2018

Вы можете попробовать это:

L.left ? chkL(L.left) : "else condition"

Вы можете добавить еще условие, если вам нужно

0 голосов
/ 07 июня 2018

Я думаю, что вы должны использовать что-то вроде этого:

if (t1.left && t1.left.val) {
  // do stuff
}

это если выражение просто оценивается как ложное, если свойство val не существует в оставленном объекте и не сломается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...