【问题标题】:Erlang Iterating through list removing one elementErlang遍历列表删除一个元素
【发布时间】:2012-06-13 12:37:08
【问题描述】:

我有以下 erlang 代码:

lists:all(fun(Element) -> somefunction(TestCase -- [Element]) end, TestCase).

TestCase 是一个数组。我正在尝试遍历缺少一个元素的列表/数组。

问题是这段代码在最坏的情况下需要 O(N^2) 时间,因为每次调用 -- 时都会复制 TestCase 数组。在非函数式语言中有一个明确的 O(N) 解决方案。

saved = TestCase[0]
temp = 0
NewTestCase = TestCase[1:] 
for a in range(length(NewTestCase)):
  somefunction(NewTestCase)
  temp = NewTestCase[a]
  NewTestCase[a] = saved
  saved = temp

...或类似的东西。

erlang 中是否有 O(N) 的解决方案?

【问题讨论】:

  • 链表对这种操作效率不高。改用sets 数据结构,你会看到效率飙升。

标签: list functional-programming erlang runtime


【解决方案1】:

当然,如果可以接受,您可以将列表拆分为 2 个子列表。

witerate(Fun, [Tail], Acc) ->
  Fun([], Acc);

witerate(Fun, [Head | Tail], Acc) ->
  Fun(Tail, Acc),
  witerate(Fun, Tail, [Head | Acc]).

【讨论】:

    【解决方案2】:

    当然有,但是有点复杂。我假设some_function/1 确实是一个布尔函数,您想测试它是否对每个子列表都返回true。

    test_on_all_but_one([], _Acc) -> true;
    test_on_all_but_one([E|Rest], Acc) ->
      case somefunction(lists:reverse(Acc,Rest)) of
        true  -> test_on_all_but_one(Rest, [E|Acc]);
        false -> false
      end.
    

    这个实现仍然是 O(length(List)^2),因为 lists:reverse/2 调用仍然需要 O(length(Acc))。如果您可以修改somefunction/1 以在拆分为两部分的列表上进行计算,那么您可以使用somefunction(Acc, Rest) 或类似的方式修改先前对somefunction(lists:reverse(Acc,Rest)) 的调用并避免重建。

    修改取决于somefunction/1 的内部运作。如果您需要更多帮助,请提供一些代码!

    【讨论】:

      猜你喜欢
      • 2013-08-05
      • 2014-04-12
      • 2012-12-05
      • 2017-02-08
      • 2010-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多