【问题标题】:Functionally add a list of Integers在功能上添加整数列表
【发布时间】:2012-11-16 18:03:24
【问题描述】:

正如标题所说,我正在尝试使用函数式编程范式添加一个整数列表。所以,根本没有突变。这是一个家庭作业,我的教授已经设置了方法定义,这也是我卡住的部分原因,这就是我目前所拥有的:

public static Integer sum(final List<Integer> values) {
     if(values.size() == 1) {
             return values.get(0);
     }
     else {
             List<Integer> tempList;
             tempList = values.subList(0, values.size() - 1);
             return sum(tempList);
     }
 }

我只能返回一个 List,并且在创建后不能以任何方式对其进行修改,并且由于使用了泛型 List,因此无法访问构造函数。 我可能会以错误的方式解决这个问题,我试图想办法将列表中的最后两个值相加,并将总和放在一个索引较短的新列表的最后一个位置。 如果您看到更好的方法来执行此操作,或者可以将我推向答案,我将不胜感激,它的作业,所以不要寻找完整的代码块。提前致谢。

【问题讨论】:

  • 你必须使用递归吗?如果没有,请参阅 Bohemian 的回复。这是最合乎逻辑的解决方案。
  • 请注意,您的代码会导致空列表异常。通常 sum 函数是用空列表作为基本情况定义的 - 而不是大小为 1 的列表。

标签: java recursion functional-programming


【解决方案1】:

您的else 分支应包含列表中的第一个数字。此外,您应该在对List.sublist 的调用中修复第二个参数。 List.sublist(fromIndex, toIndex) 的两个参数指定一个子列表。 fromIndex 包含但 toIndex 是独占的。

【讨论】:

  • 他不是说他不是在寻找一个完整的代码块吗? :)
  • (+1) 不错的提示。我唯一的 cmets 是 “第一个数字” 与他已经拥有的代码不太一致(应该是 last)。
  • repro,在你编辑它之前,我看了你的代码大约 2 秒钟,呵呵。两个问题: sum(list) 做了什么,您能否更具体地说明我的子列表有什么问题?谢谢。
  • @JakeSellers 如果你真的想看他的代码,他的答案的完整修订历史在这里:stackoverflow.com/posts/13612704/revisions
  • 啊,谢谢,但我还是想了解他在做什么,而不仅仅是复制粘贴。
【解决方案2】:

编辑:

哦,我明白了 - 你想要一个 递归 解决方案。试试这个单行代码,它在技术上甚至不使用if 声明:

public static Integer sum(final List<Integer> values) {
     return values.isEmpty() ? 0 : values.get(0) + sum(subList(1, values.size());
}

这可能会让你得到 9/10 的分数。要获得满分,您需要添加 null 安全性:

public static Integer sum(final List<Integer> values) {
     return values == null || values.isEmpty() ? 0 : values.get(0) + sum(subList(1, values.size());
}

完全披露,以前我有这个:

你的代码太多了!

public static Integer sum(final List<Integer> values) {
     int total = 0;
     for (int i : values) {
         total += i;
     }
     return total;
}

仅供参考,自动装箱在intInteger 之间平滑转换

【讨论】:

  • 我没有投票,但他确实说使用函数式编程范例。我不认为 for 循环计数。 :)
  • 您在代码中使用了可变变量 (total)。这不是我们所要求的。
  • 是的,所有的赋值语句和循环都是无效的。
【解决方案3】:

您的原始答案非常接近。

提示:你得到一个由原始列表减去最后一个元素组成的子列表,但你只是把最后一个元素扔掉——你永远不会使用它的值。也许它应该包含在子列表的总和中? (答案 = 是)

另外,我可能会在方法的顶部添加:

if (values == null || values.isEmpty())
{
  return null;
}

【讨论】:

  • 空整数列表的总和传统上称为0,而不是null。 Null 会导致足够多的问题,但不会为完全指定的输入值返回它们。
  • 我可能确信空列表会返回 0(尽管尚未确信),但我当然不会为空列表返回 0。返回 null 或抛出 IAE 可能会更好。
  • 空和 0。如果你认为乘法是重复加法,3 * xx + x + x。所以加在一起 ​​0 xs 应该对应于0 * x。类似地,空积是 1(x^0 = 1),空析取(|| 布尔列表)是 false,空合取(&amp;&amp; 布尔列表)是 true。像sum 操作这样通用的东西确实应该与sum 的标准数学定义一致。我同意null 不是一个空列表,而是一个定义不明确的列表,并且没有明确的总和。
【解决方案4】:

在 Haskell 中添加一个列表,作为查看明显解决方案的一种方式。 sum 是一个加法的文件夹:

 sum xs = foldr (+) 0 xs

内联折叠器

 sum xs = go (+) 0 xs
     where
         go _ z []     =  z
         go f z (x:xs) =  f x (go f z xs)

专攻 (+)

 sum xs = go xs
     where
         go []     = 0
         go (x:xs) = x + (go xs)

内联去得到我们的最终答案:

 sum []     = 0
 sum (x:xs) = x + sum xs

这就是基本的递归解决方案。它同样适用于空列表或具有一个或多个元素的列表。可以直接翻译成Java(我的Java超级生疏):

 public static Integer sum(final List<Integer> xs) {
     if(xs.size() == 0) {
         return 0;
     } else {
         return xs.get(0) + sum(subList(1, xs.size());
     }
 }

【讨论】:

    猜你喜欢
    • 2018-06-29
    • 2018-03-06
    • 1970-01-01
    • 2019-10-25
    • 2016-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多