Python __repr__ 方法:写一个 JS 等价物?

Python __repr__ method: writing a JS equivalent?

我正在学习一个关于算法和数据结构的短期初学者课程。导师的语言是Python;我正在将代码示例转换为 JavasScript。到目前为止,还不错。

我正在处理链表。讲师使用 Python 的 __repr__() 方法测试代码。经过几天的反复试验,我有了一个有效的 JS 解决方案,但它与 Python 代码并不完全相同。我想知道是否有更好的方法来实现我提供的 JS 代码以及 Python 代码。

Python

# class LinkedList and its methods are presumed to exist

def __repr__(self):
  
  nodes = []
  current = self.head

  while current:
    if current is self.head:
      nodes.append("[Head: %s]" % current.data)
    elif current.next_node is None:
      nodes.append("[Tail: %s]" % current.data)
    else
      nodes.append("[%s]" % current.data)

    current = current.next_node
  return '-> '.join(nodes)

# running script
>>> l = LinkedList()
>>> l.add(1)
>>> l.add(2)
>>> l.add(3)
>>> l
[Head: 3]-> [2]-> [Tail: 1]  # output
>>>

JS

// class LinkedList and its methods are presumed to exist

repr () {
  
  let nodes = "";
  let current = this.head;

  while (current) {
    if (current === this.head) {
      nodes = `Head: ${current.data}-> `;
    } else if (current.nextNode === null) {
      nodes += `Tail: ${current.data}`;
    } else {
      nodes += `${current.data}-> `;
    }
    current = current.nextNode;
  }
  return nodes;

// running the script
let l = LinkedList();
l.add(1);
l.add(2);
l.add(3);

let result = l.repr();
console.log(result);  // Head: 3-> 2-> Tail: 1

同样,这两个片段只会 运行 在链表算法的完整实现中,但它们确实有效。

我所做的尝试:我尝试使用 JS toString()append()appendChild(),但它们太难了,我无法理解如何最好地使用它们,尤其是作为最后两个修改DOM。我确定有更好的方法来实现相当于 Python __repr__(); 的 JS;我想知道怎么做。

更接近的实现将使用 toString 方法。当需要转换为字符串时,将隐式调用此方法。 Python 实际上有两种方法,目的略有不同:__repr____str__。 JavaScript.

中没有这种区别

此外,我们应该意识到 Python 的 print 将隐式调用 __repr__,这不是 console.log 的工作方式。因此,对于 console.log,您必须强制转换为字符串。

下面是给定的 Python 代码最直译的方式(我将 运行 脚本所需的 类 添加到脚本中):

class Node {
    constructor(data, next=null) {
        this.data = data;
        this.next_node = next;
    }
}

class LinkedList {
    constructor() {
        this.head = null;
    }
    add(data) {
        this.head = new Node(data, this.head);
    }
    toString() {
        let nodes = [];
        let current = this.head;
        while (current) {
            if (current === this.head) {
                nodes.push(`[Head: ${current.data}]`);
            } else if (current.next_node === null) {
                nodes.push(`[Tail: ${current.data}]`);
            } else {
                nodes.push(`[${current.data}]`);
            }
            current = current.next_node;
        }
        return nodes.join('-> ');
    }
}

// running script
let l = new LinkedList();
l.add(1);
l.add(2);
l.add(3);
// Force conversion to string
console.log(`${l}`); // [Head: 3]-> [2]-> [Tail: 1]

就个人而言,我会进行以下更改(未反映在 Python 版本中):

  • 生成没有“Head”和“Tail”以及其他“修饰”字样的输出。这对我来说太冗长了。只输出分隔值。
  • 使列表实例可迭代,实现 Symbol.iterator 方法(在 Python 中:__iter__)。然后使用它来实现 toString 方法。
  • 允许列表构造函数采用任意数量的值来填充列表。

这导致以下版本:

class Node {
    constructor(data, next=null) {
        this.data = data;
        this.next = next;
    }
}

class LinkedList {
    constructor(...values) { // Accept any number of values
        this.head = null;
        // Populate in reverse order
        for (let data of values.reverse()) this.add(data);
    }
    add(data) {
        this.head = new Node(data, this.head);
    }
    // Make lists iterable
    *[Symbol.iterator]() {
        let current = this.head;
        while (current) {
            yield current.data;
            current = current.next;
        }
    }
    toString() {
        // Array.from triggers the above method
        return Array.from(this).join("→");
    }
}

// Provide the desired values immediately:
let l = new LinkedList(3, 2, 1);
console.log(`${l}`); // 3→2→1