【问题标题】:Map, reduce, filter apply to for loops and while loopsMap、reduce、filter 适用于 for 循环和 while 循环
【发布时间】:2016-09-19 04:40:39
【问题描述】:

我是 Julia 新手,正在学习使用 Map、reduce、filter。 我越来越难以理解它如何替代 for 和 while 循环。 对于下面的代码,我想替换 for 循环

function addMultiplesOf3And5(N::Int)
  sumOfMultiples = 0
  if(N == 3)
    return sumOfMultiples + N
  end
  for i = 3:N-1
    if(i % 3 == 0 && i % 5 == 0)
      continue
    elseif(i % 3 == 0)
      sumOfMultiples += i
    elseif(i % 5 == 0)
      sumOfMultiples += i
    end
  end

  return sumOfMultiples
end

非常感谢您的帮助。

更新: 这是我通过教程后所做的

function addMultiplesOf3And5(N::Int)
  array = range(1,N-1)
  return reduce(+, map(x -> multiples_of_3_Or_5(x), array))
end

function multiples_of_3_Or_5(n)
  if(n % 3 == 0 && n % 5 == 0)
    return 0
  elseif(n % 3 == 0)
    return n
  elseif(n % 5 == 0)
    return n
  else
    return 0
  end
end

决赛:

function addMultiplesOf3And5(N::Int)
  array = range(1,N-1)
  return reduce(+, filter(x -> ((x%3==0)$(x%5==0)), array))
end

【问题讨论】:

  • 也许可以提供一些关于您迄今为止尝试过的细节。另见StackOverflow Homework Guidelines
  • 自从我使用 map 函数已经有一段时间了,但据我回忆,它对列表的每个元素都应用了一个函数。所以当然 for 循环也可以做到这一点。所以应该清楚如何使用 for 循环来代替。

标签: julia


【解决方案1】:

要了解如何将“for 循环 + if 块”代码替换为“map / reduce / filter”,您需要确切了解它们的工作原理以及为什么选择它们。


1。 map 函数

map 是一个函数,它接受一个function 变量和一个列表作为参数,并返回一个new 列表,其中每个元素都是应用函数的结果到旧列表的每个元素。例如,如果您的变量f 引用了您之前定义的函数f(x) = x + 5,并且您有一个列表L=[1,2,3,4,5],那么map(f, L) 将返回[f(L[1]), f(L[2]), f(L[3]), f(L[4]), f(L[5])]

所以如果你有这样的代码:

f(x) = x + 5;
L = [1,2,3,4,5];
A = zeros(5);
for i in L
  A[i] = f(i);
end

您可以像这样将其重写为映射操作:

A = map(x -> x + 5, [1,2,3,4,5]);

2。 reduce 函数

reduce 接受一个 binary 函数变量(即一个接受两个参数的函数)和一个列表作为参数。它的作用可能最好用一个例子来解释。使用+ 运算符调用reduce,并列出[1,2,3,4,5] 将执行以下操作:

Step 1:   [1, 2, 3, 4, 5]  %           : 5 elements
Step 2:   [1+2, 3, 4, 5]   % [3,3,4,5] : 4 elements
Step 3:   [3+3, 4, 5]      % [6, 4, 5] : 3 elements 
Step 4:   [6+4, 5]         % [10, 5]   : 2 elements
Step 5:   [10+5]           % [15]      : 1 elements
result: 15

即我们通过将二元函数连续应用于第一对元素,将列表缩减为单个结果,一点一点地消耗列表。

所以如果你有这样的代码:

f(x,y) = x + y
L = [1,2,3,4,5];
A = L[1];
for i in 2:length(L)
  A = f(A, L[i])
end

您可以将其重写为 reduce 操作,如下所示:

A = reduce(x,y -> x+y, [1,2,3,4,5])

3。 filter 函数

filter 采用 谓词 函数(例如 isevenisnull== 或任何接受参数并对其执行测试的任何东西,结果为真或假)和一个列表,使用函数测试列表中的每个元素并返回一个新列表,该列表仅包含通过该测试的元素。例如

filter(iseven, [1,2,3,4,5])   # returns [2,4]

问题的答案

如果我理解正确,addMultiplesOf3And5 接受一个数字 N(例如 20),然后执行以下操作:

  • 过滤从列表 [1,2,3,...,20] 中过滤掉所有可以被 3 或 5 整除的元素
  • 使用 reduce 函数将结果列表的所有元素连续相加。

您应该能够使用上面的代码来找出确切的代码:)

【讨论】:

  • 朱莉娅!我用于探索性数据分析的新语言
【解决方案2】:

不确定问题中的函数应该计算什么,但是:

addMult3or5(N) = N==3 ? 3 : sum(filter(x->((x%3==0)$(x%5==0)),3:N-1))

计算同样的事情。

sum 是一个类似reduce 的函数,用于+ 操作。

希望这有助于澄清。

另外,$ 是 Julia 中的异或运算。

【讨论】:

  • 您可以将sum(x) 替换为reduce(+, x),如果这样可以更清楚地了解它的关系。 (顺便说一句,我猜这是 FizzBu​​zz 的变种))
  • 是否可以 chain 函数而不是嵌套它们 - 例如collection.filter(predicate).map(predicate).sum ?
  • @javadba 管道运算符|> 在这种情况下允许一些链接,即filter(x->((x%3==0)⊻(x%5==0)),3:N-1) |> sum。另请注意 xor 运算符从 $ 更改为
  • 更多管道版本可能是:addMult3or5(N) = N==3 ? 3 : 3:N-1 |> v->filter(x->((x%3==0)⊻(x%5==0)),v) |> sum
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-18
  • 2017-01-28
  • 1970-01-01
  • 2021-06-06
  • 1970-01-01
  • 2014-02-01
  • 1970-01-01
相关资源
最近更新 更多