JSON.stringify嵌套了Set的Map

huangapple go评论99阅读模式
英文:

JSON.stringify Map with nested Set

问题

考虑以下图形:

  1. class Node {
  2. constructor(value) {
  3. this.value = value;
  4. this.adjacents = new Set();
  5. }
  6. addAdjacent(node) {
  7. this.adjacents.add(node);
  8. }
  9. }
  10. class Graph {
  11. constructor(directed = false) {
  12. this.nodes = new Map();
  13. this.directed = directed;
  14. }
  15. addVertex(value) {
  16. const node = this.nodes.has(value);
  17. if (node) {
  18. return this.nodes.get(value);
  19. }
  20. const vertex = new Node(value);
  21. this.nodes set(value, vertex);
  22. return vertex;
  23. }
  24. addEdge(src, dest) {
  25. let srcNode = this.nodes.get(src);
  26. if (!srcNode) {
  27. srcNode = this.addVertex(src);
  28. }
  29. let destNode = this.nodes.get(dest);
  30. if (!destNode) {
  31. destNode = this.addVertex(dest);
  32. }
  33. srcNode.addAdjacent(destNode);
  34. if (this.directed === false) {
  35. destNode.addAdjacent(srcNode);
  36. }
  37. }
  38. }
  39. const g1 = new Graph();
  40. g1.addVertex("a");
  41. g1.addVertex("b");
  42. g1.addEdge("a", "c");

当我使用 console.log 输出图形对象 g1 时,我得到以下输出:

  1. Graph {
  2. nodes: Map(3) {
  3. 'a' => Node { value: 'a', adjacents: [Set] },
  4. 'b' => Node { value: 'b', adjacents: Set(0) {} },
  5. 'c' => Node { value: 'c', adjacents: [Set] }
  6. },
  7. directed: false
  8. }

正如输出所示,我没有获取有关顶点的边的信息。

我尝试将 replacer 传递给 JSON.stringify 如下,但会导致栈溢出错误。

  1. console.log(
  2. JSON.stringify(
  3. Object.fromEntries(g1.nodes),
  4. (_key, value) =>
  5. value.adjacents instanceof Set ? [...value.adjacents] : value,
  6. 2
  7. )
  8. );

错误:

  1. JSON.stringify(
  2. ^
  3. RangeError: Maximum call stack size exceeded
  4. at JSON.stringify (<anonymous>)

如何以更友好的格式打印图形?

英文:

Consider the following graph:

  1. class Node {
  2. constructor(value) {
  3. this.value = value;
  4. this.adjacents = new Set();
  5. }
  6. addAdjacent(node) {
  7. this.adjacents.add(node);
  8. }
  9. }
  10. class Graph {
  11. constructor(directed = false) {
  12. this.nodes = new Map();
  13. this.directed = directed;
  14. }
  15. addVertex(value) {
  16. const node = this.nodes.has(value);
  17. if (node) {
  18. return this.nodes.get(value);
  19. }
  20. const vertex = new Node(value);
  21. this.nodes.set(value, vertex);
  22. return vertex;
  23. }
  24. addEdge(src, dest) {
  25. let srcNode = this.nodes.get(src);
  26. if (!srcNode) {
  27. srcNode = this.addVertex(src);
  28. }
  29. let destNode = this.nodes.get(dest);
  30. if (!destNode) {
  31. destNode = this.addVertex(dest);
  32. }
  33. srcNode.addAdjacent(destNode);
  34. if (this.directed === false) {
  35. destNode.addAdjacent(srcNode);
  36. }
  37. }
  38. }
  39. const g1 = new Graph();
  40. g1.addVertex("a");
  41. g1.addVertex("b");
  42. g1.addEdge("a", "c");

When I console.log the graph object g1. I get the following output:

  1. Graph {
  2. nodes: Map(3) {
  3. 'a' => Node { value: 'a', adjacents: [Set] },
  4. 'b' => Node { value: 'b', adjacents: Set(0) {} },
  5. 'c' => Node { value: 'c', adjacents: [Set] }
  6. },
  7. directed: false
  8. }

As output shows, I get no info regarding the edges of the vertices.

I tried passing replacer to JSON.stringify as follows, but it results in StackOverFlow error.

  1. console.log(
  2. JSON.stringify(
  3. Object.fromEntries(g1.nodes),
  4. (_key, value) =>
  5. value.adjacents instanceof Set ? [...value.adjacents] : value,
  6. 2
  7. )
  8. );

Error:

  1. JSON.stringify(
  2. ^
  3. RangeError: Maximum call stack size exceeded
  4. at JSON.stringify (<anonymous>)

How can I print the graph in a more friendly format?

答案1

得分: 3

  1. 两个问题:

    1. MapSet 都无法直接序列化为 JSON。
    2. 您的数据结构是循环的,因此无法进行序列化;节点 a 与节点 c 相邻,节点 c 与节点 a 相邻。尝试将其序列化为扁平结构将需要无限的存储空间。

我建议在您的类中添加一个 toJSON() 方法来辅助序列化。在这里,无法序列化的数据结构可以转换为简单的数据结构,循环引用可以被解除。

例如:

  1. class Node {
  2. constructor(value) {
  3. this.value = value;
  4. this.adjacents = new Set();
  5. }
  6. addAdjacent(node) {
  7. this.adjacents.add(node);
  8. }
  9. toJSON() {
  10. return {
  11. ...this,
  12. // plain array with scalar values
  13. adjacents: [...this.adjacents].map(({ value }) => value),
  14. };
  15. }
  16. }
  17. class Graph {
  18. constructor(directed = false) {
  19. this.nodes = new Map();
  20. this.directed = directed;
  21. }
  22. addVertex(value) {
  23. const node = this.nodes.has(value);
  24. if (node) {
  25. return this.nodes.get(value);
  26. }
  27. const vertex = new Node(value);
  28. this.nodes.set(value, vertex);
  29. return vertex;
  30. }
  31. addEdge(src, dest) {
  32. let srcNode = this.nodes.get(src);
  33. if (!srcNode) {
  34. srcNode = this.addVertex(src);
  35. }
  36. let destNode = this.nodes.get(dest);
  37. if (!destNode) {
  38. destNode = this.addVertex(dest);
  39. }
  40. srcNode.addAdjacent(destNode);
  41. if (this.directed === false) {
  42. destNode.addAdjacent(srcNode);
  43. }
  44. }
  45. toJSON() {
  46. return {
  47. ...this,
  48. // reduce the Map entries to a simple object
  49. nodes: Object.fromEntries(this.nodes),
  50. };
  51. }
  52. }
  53. const g1 = new Graph();
  54. g1.addVertex("a");
  55. g1.addVertex("b");
  56. g1.addEdge("a", "c");
  57. console.log(JSON.stringify(g1, null, 2));
  1. 这是您提供的代码部分的翻译。
  2. <details>
  3. <summary>英文:</summary>
  4. There&#39;s two issues here...
  5. 1. Both `Map` and `Set` do not serialise directly to JSON
  6. 2. Your data structure is cyclic and therefore cannot be serialised; node _a_ is adjacent to node _c_ and node _c_ is adjacent to node _a_. Attempting to serialise this to a flat structure would require infinite storage.
  7. I would recommend adding a [toJSON()][1] method to your classes to aid in the serialisation. There, unserialisable data structures can be converted to simple ones and cyclic references can be broken.
  8. For example
  9. &lt;!-- begin snippet: js hide: false console: true babel: false --&gt;
  10. &lt;!-- language: lang-js --&gt;
  11. class Node {
  12. constructor(value) {
  13. this.value = value;
  14. this.adjacents = new Set();
  15. }
  16. addAdjacent(node) {
  17. this.adjacents.add(node);
  18. }
  19. toJSON() {
  20. return {
  21. ...this,
  22. // plain array with scalar values
  23. adjacents: [...this.adjacents].map(({ value }) =&gt; value),
  24. };
  25. }
  26. }
  27. class Graph {
  28. constructor(directed = false) {
  29. this.nodes = new Map();
  30. this.directed = directed;
  31. }
  32. addVertex(value) {
  33. const node = this.nodes.has(value);
  34. if (node) {
  35. return this.nodes.get(value);
  36. }
  37. const vertex = new Node(value);
  38. this.nodes.set(value, vertex);
  39. return vertex;
  40. }
  41. addEdge(src, dest) {
  42. let srcNode = this.nodes.get(src);
  43. if (!srcNode) {
  44. srcNode = this.addVertex(src);
  45. }
  46. let destNode = this.nodes.get(dest);
  47. if (!destNode) {
  48. destNode = this.addVertex(dest);
  49. }
  50. srcNode.addAdjacent(destNode);
  51. if (this.directed === false) {
  52. destNode.addAdjacent(srcNode);
  53. }
  54. }
  55. toJSON() {
  56. return {
  57. ...this,
  58. // reduce the Map entries to a simple object
  59. nodes: Object.fromEntries(this.nodes),
  60. };
  61. }
  62. }
  63. const g1 = new Graph();
  64. g1.addVertex(&quot;a&quot;);
  65. g1.addVertex(&quot;b&quot;);
  66. g1.addEdge(&quot;a&quot;, &quot;c&quot;);
  67. console.log(JSON.stringify(g1, null, 2));
  68. &lt;!-- language: lang-css --&gt;
  69. .as-console-wrapper { max-height: 100% !important; }
  70. &lt;!-- end snippet --&gt;
  71. [1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#description
  72. </details>

huangapple
  • 本文由 发表于 2023年6月8日 08:36:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/76427919.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定