【问题标题】:How to set a JSON path in array in Javascript? [duplicate]如何在 Javascript 中的数组中设置 JSON 路径? [复制]
【发布时间】:2015-11-29 18:44:35
【问题描述】:

我有这个 JSON

var myJSON = {
    "a": {
        "b": {
            "c": {
                "Foo": "Bar"
            }
        }
    }
}

我也有这个数组:

var path = ["a", "b", "c", "foo"]

如何使用路径获取Bar

【问题讨论】:

  • var x = myJSON; path.each(function(key, val) { x = x[key]; } 会采用(希望工作)肮脏的方式。

标签: javascript arrays json


【解决方案1】:

查看Array.prototype.@987654321@。这将从myJSON 开始,然后遍历path 中定义的每个嵌套属性名称。

var myJSON = {
  "a": {
    "b": {
      "c": {
        "Foo": "Bar"
      }
    }
  }
};

var path = ["a", "b", "c", "Foo"]; // capitalized Foo for you...

var val = path.reduce((o, n) => o[n], myJSON);

console.log("val: %o", val);

【讨论】:

  • 通过额外检查未定义的值,这是我通常采用的解决方案,简洁明了。由于我现在已经多次回到这个答案,如果这个问题没有作为重复问题关闭,我会添加赏金作为奖励。
  • @nit 欺骗目标的accepted answer 建议eval()... :/
  • 你的答案显然更好,但我不确定是投票重新打开还是标记,因为欺骗标记也用于另一个问题。
  • 那些欺骗链是有趣的野兽......
【解决方案2】:

拥有一个存储对象值的变量,然后遍历path 访问该变量中的下一个属性,直到下一个属性未定义,此时该变量保存结束属性。

var val = myJSON;

while (path.length) {
    val = val[path.shift()];
}

console.log(val);

【讨论】:

  • 你不应该检查 path[0] 而不是 val[path[0]]?
  • 请注意,移位可能是 O(N) 而不是 O(1),尽管它可能取决于其实现方式
  • path.reverse() 在进入 while 之前(双关语:D),然后是 pop()the hell outta it!
  • @KyleMit 那是因为你已经通过缓存path 破坏了测试。因此,在shift()pop() 测试运行一次之后,path 中没有任何东西可以处理剩余的迭代。从那时起,path.length 将变为0,从而跳过while() 循环。也就是说,pop() 即使使用合法测试也可能更快。
  • @canon,好的,这是一个fixed version,现在按顺序排列为pop、reduce、shift
【解决方案3】:
function access(json, path, i) {
  if (i === path.length)
    return json;
  return access(json[path[i]], path, i + 1);
}

使用:

access(myJSON, path, 0)

【讨论】:

  • 完全没有必要使用递归。迭代方法通常性能更高,并且堆栈跟踪也更便于在出现错误时进行分析。
  • 除了递归可以通过归纳证明,因此更容易调试
  • 确实比较慢,但它仍然是一种有趣的方法。递归就像是心灵的糖:)
  • @twinlakes 这与调试的难易程度无关。
  • 我想说树遍历是递归最常见的情况之一,这是 OP 教科书问题的教科书答案。它也比迭代方法更容易理解。
【解决方案4】:
var myJSON = {
    "a": {
        "b": {
            "c": {
                "Foo": "Bar"
            }
        }
    }
}

var path = ["a", "b", "c", "Foo"]


var findViaPath = function (path, object) {
    var current = object;

    path.forEach(function(e) { 
        if (current && e in current) {
            current = current[e];
        } else {
            throw new Error("Can not find key " + e)
        }
    })

    return current;
}

findViaPath(path, myJSON);

【讨论】:

  • @canon,感谢您提供解释。这对问题 OP、答案 OP 以及任何希望找出实施哪种解决方案的未来旅行者都有帮助。此外,除了性能可能较低之外 - 我不确定它是否过度设计。当然,它将检查包装在一个函数中并提供一些错误检查,但这并不是世界上最糟糕的事情。相关的是,看起来像 Foo: false 的数据将引发错误 current(e) = current('Foo') = false
  • @canon,看起来forEachreduce 都比一个小鬼更糟糕for 循环jsperf.com/array-reduce-vs-foreach/9 - 但他们基本上都在做同样的事情。此解决方案中的(现已修复)错误检查可以添加到任何其他解决方案中,以使其更加健壮。
  • 这里是another test。我认为,如果我们要将 forEach 添加到 jsPerf 中,那么我们必须将苹果与苹果进行比较,而不包括额外的错误检查或函数调用(我认为这两者实际上都是清晰的好东西。这个奇怪的循环是做什么的?哦,它在一个告诉我的函数内部!就错误检查而言,完整的路径会很好。
猜你喜欢
  • 1970-01-01
  • 2015-11-09
  • 1970-01-01
  • 2021-11-16
  • 1970-01-01
  • 2016-04-21
  • 1970-01-01
  • 1970-01-01
  • 2014-09-28
相关资源
最近更新 更多