在列表中向上移动项目

时间:2014-01-13 14:18:04

标签: list f#

如何在列表中移动项目 输入列表如下所示:let list = [1;2;3;4;5]
输出列表看起来像下列之一:
[1;2;3;5;4]
.........>

[2;1;3;4;5]
...>......

情节扭曲:我希望能够移动列表中的任何索引

据我所知,这不是你想用F#或函数式语言做的事情,但它是我的程序必备的。
我相信这可以使用递归和高阶(HO)函数来完成,但由于我对HO的知识非常有限,我尝试使用递归来解决这个问题。

我在列表中向下移动项目的方法包括一个简单的递归,索引和列表作为参数,如下所示:

let rec moveDownAt index list =
    match index, list with
    | -1, _ -> list
    | 0, h1::h2::t -> h2::h1::t
    | index, h::t -> h::moveDownAt (index - 1) t
    | _, [] -> list

然而,为了向另一个方向移动,我需要引用前面的“头部”,我假设我会在第三个匹配线| index, h::t -> h::moveDownAt (index - 1) t上遇到问题,我执行h ::,因为我添加了头部列表(如果我添加该参数,那将是前一个下一个调用)。

2 个答案:

答案 0 :(得分:2)

在两个元素上切换位置意味着一个向上移动,一个向下移动 使用以下代码简单就可以解决问题:

let moveUpAt index list = moveDownAt (index-1) list

这将取代索引使“索引向下移动”变成“索引向上移动”。

答案 1 :(得分:1)

基本思想如下:首先,返回列表的n元素。然后追加除n元素之外的其余元素,因为您已经返回了它。这是代码:

let MoveToTop index xs =
    List.nth xs index           // take nth item
    ::                          // and prepend it to the beginning of the
                                // original list, except the nth element
    (
        xs                      // original data
        |> List.mapi
            (fun i x -> i, x)   // associate each element with its ordinal index
        |> List.filter
            (fun (i, _) -> i <> index) // allow only the elements whose index
                                       // is not equal to requested index
        |> List.map snd         // remove the index from the data
                                // as we no longer need it
    )

// test
[1; 2; 3; 4; 5]
|> MoveToTop 1 // don't forget, the index is zero-based
|> printfn "%A"
// output: [2; 1; 3; 4; 5]

请注意,如果index超出列表的长度,则会抛出ArgumentException

递归算法也是可能的,但由于过多的数据创建和执行过多的计算,它肯定会降低性能。