如何修改给定索引处的List元素

时间:2016-04-11 15:06:30

标签: elm

我所做的(在朋友的帮助下)创建了一个函数,该函数对索引采用var getSongs = function(number, year, db, callback) { var collection = db.collection('songsList'); var songIds = []; var chartSongs = []; for (var i = 0; i < number; i++) { // Get one random document from the collection. collection.aggregate([ { $match: { '_id': { '$nin': songIds }, 'songYear': year } }, { $sample: { size: 1 } } ], function(err, chart) { songIds.push(chart[0]._id); chartSongs.push(chart[0]); if (songIds.length === number) { callback(chartSongs); } }) } }; List,并在以下函数中应用函数指定的索引。它与Int类似,但不是将函数应用于每个元素,而是仅将其应用于一个元素。

所以我的问题是:

  • 这个功能是否已存在于核心某处?我们无法找到它。
  • 如果没有,是否有更好的方法来实现这一点,而不是我们如何做到这一点?

以下是代码:

Map

注意:Elm discourages indexing Lists, as they are linked lists under the hood: to retrieve the 1001th element, you have to first visit all 1000 previous elements.尽管如此,如果你想这样做,这是一种方式。

2 个答案:

答案 0 :(得分:1)

List.indexedMap是一个很好的方式来做你正在描述的事情。

然而,既然你提到了必须访问列表中所有前面元素的缺点,那么你的例子中的实际情况实际上有点糟糕,如果你真的对性能非常担心。

无论索引是否存在,您的列表实际上至少完全遍历了两次。询问链表长度的简单行为必须遍历整个列表。查看源代码length is implemented in terms of a foldl

此外,List.indexedMap至少遍历整个列表一次。我说,至少一次,因为除了使用indexedMap之外,map的来源还calls the length function。如果我们很幸运,length电话会被记忆(我对Elm内部不熟悉,不知道是否存在,因此至少评论)。 map本身在被调用时遍历整个列表,不像Haskell懒惰地评估事物,只是必要时。

如果您使用indexedMap,则无论您感兴趣的位置如何,都会对整个列表编制索引。也就是说,即使您要在索引0处应用该函数,也会对整个列表编制索引。

如果您确实希望将遍历次数减少到最少,那么(此时)您必须实现自己的功能,而您必须在不依赖length的情况下执行此操作。 indexedMap

这是一个changeAt函数的示例,它避免了不必要的遍历,如果找到了位置,它就会停止遍历列表。

changeAt : List a -> Int -> (a -> a) -> Result String (List a)
changeAt l i func =
  if i < 0 then
    Err "Bad Index"
  else
    case l of
      [] ->
        Err "Not found"
      (x::xs) ->
        if i == 0 then
          Ok <| func x :: xs
        else
          Result.map ((::) x) <| changeAt xs (i - 1) func

它并不是非常漂亮,但是如果你想避免不必要地遍历列表 - 多次 - 那么你可能想要用这样的东西。

答案 1 :(得分:0)

您正在寻找the set function for Arrays。而不是像你所描述的那样使用低效的List,这种结构更适合你的用例。

这是您正在寻找的功能的有效实现:

changeAt : Int -> (a -> a) -> Array a -> Array a
changeAt i f array =
case get i array of
    Just item ->
        set i (f item) array
    Nothing ->
        array

另请注意此实现中的data structure is the last argument

您的问题中的链接中提到了

Array,但此帖子中没有人明确提到此选项。