我正在尝试使用不变性,高阶函数和/或递归(无循环或变异)在函数式语言中实现以下算法。
算法迭代一个列表,对于每对相邻元素,如果左边大于右边,则交换它们。
但是,如果两个相邻元素之间的差异小于某个数字(比如10
),则应使用这些作为参数调用函数(notify
)
关于如何重写它的任何提示?
for (i = 1, i < queue.legth, i++) {
left = queue[i-1]
right = queue[i]
if (abs(left - right) < 10) {
notify(left, right)
} else if (left > right) {
queue[i-1] = right
queue[i] = left
}
}
更新
是的,不是改变列表,而是应该返回一个新列表
答案 0 :(得分:2)
JavaScript是一种可怕的语言。但这是一个想法。
首先实现链接列表。您的API可能包含以下命令:
var empty_list = create_empty_list()
var larger_list = list.prepend(thing)
var is_empty = list.is_empty()
var first_element = list.head()
var tail = list.tail()
var reversed_list = list.reversed()
在内部,链表只是一个带头的对象,另一个是指向尾的对象。因此,在列表前面只是意味着创建一个新节点,其新值指向旧节点。 (即不是变异!)所以你有了访问者。然后reversed
是一个简单的递归函数。 (您需要一个帮助函数list._reversed(tail)
,然后list.reversed()
只是list._reversed(create_empty_list())
。帮助函数返回tail
表示空列表,否则返回this.tail._reversed(tail.prepend(this.head))
。)
使用链接列表,您可以遍历队列,构建重新排列的列表并在您想要的位置调用notify
。当你完成对队列的迭代时,你会有一个完全向后的链表。但是,您可以调用reversed
以正确的顺序获取队列。