是否有更清晰的语法将操作应用于序列的每个元素?

时间:2008-12-28 18:55:14

标签: c# c#-3.0

int z = 1;
double result = Math.Log(z);            //works

然而,尝试用数组来做同样的事情是行不通的:

int[] z = new [] {1,2,3,4};
double[] result = Math.Log(z);            //Syntax 1 - error CS1503: Argument '1': cannot convert from 'int[]' to 'double'
double[] result = z.Select(p => Log(p)).ToArray();  //Syntax 2 - OK

如何使语法#1工作?语法#2对我来说似乎很脏。

7 个答案:

答案 0 :(得分:4)

不,没有更清洁的方式。 语法2 使用Select()和lambda表达式将Math.Log()应用于每个元素是在C#中执行此操作的惯用方法。

答案 1 :(得分:2)

int[] z = new [] {1,2,3,4};
double[] result = Array.ConvertAll(z, p => Log(p));

double Log(int i) { return Math.Log(i); }

int[] z = new[] { 1, 2, 3, 4 };
double[] result = Array.ConvertAll(z, Log);

答案 2 :(得分:2)

为了完整性,还应该注意到Linq最大的一个强项是扩展它的能力。

如果你做了很多这样的操作,很可能是用Log函数扩展IEnumerable的候选者,这很简单

  static class LogExtension
  {
    public static IEnumerable<Double> Log(this IEnumerable<int> list)
    {
      foreach (int i in list)
      {
        yield return Math.Log(i);
      }
    }
  }

然后简单地称之为......

IEnumerable<Double> logValues = myInts.AsEnumerable().Log();

答案 3 :(得分:1)

你可以将丑陋包含在一个功能中:

private static double[] getLogForIntArray(int[] z)
{
    double[] q = (double[])z.Select(p => Math.Log(p)).ToArray();
    return q;
}

并将其调用为语法3(并将其返回到某些内容):

double[] q = getLogForIntArray(z); // Syntax 3

答案 4 :(得分:1)

这对我来说是最干净的解决方案: -

double[] x = Array.ConvertAll(z, p => Math.Log(p));

它应该是比select更好的解决方案,因为ConvertAll预先知道返回数组中将有多少元素。我不确定选择是否属实,如果还有一些其他更强大的魔法可能会继续存在。然而,上述更清晰,因为转换意图更清晰。

答案 5 :(得分:1)

在此代码中:

int[] z = new [] {1,2,3,4};
double[] result = z.Select(p => Log(p)).ToArray();

大多数(如果不是全部)你看到的“残酷”是由于使用了数组,当问题标题为“是否有更清晰的语法将操作应用于序列的每个元素?“

在.NET 3.0中,“序列”用IEnumerable<>接口封装。

使用此功能,您最终会获得更清晰的代码:

IEnumerable<int> z = new[] {1, 2, 3, 4};
IEnumerable<double> result = z.Select(i => Math.Log(i));

通过 var 键操作使用隐式类型,事情非常清楚:

var z = new[] {1, 2, 3, 4};
var result = z.Select(i => Math.Log(i));

通常,当您使用List&lt;&gt;时,您会发现C#3.0(尤其是LINQ)的新功能发挥得非常好。而不是阵列。

如果您的代码已经基于数组,我建议您在API中添加接受IEnumerable而不是int []的重载,从而允许消费代码使用现代语言功能。

答案 6 :(得分:-1)

不太确定你在问什么,但是......

您可以为数组提供索引。


for (int i = 0; i < z.Length; i++)
{
  Math.Log(z[i]);
}

虽然我认为没有保留计算的价值没有意义吗?

修改

您可能必须使用double数据类型,因为math.log返回


        static void Process()
        {
            double[] test = { 1, 2, 3, 4 };
            double[] answer = new double[test.Length];
            for (int i = 0; i < test.Length; i++)
            {
                answer[i] = Math.Log(test[i]);
            }

        }