Существует ли более чистый синтаксис для применения операции к каждому элементу последовательности? - PullRequest
2 голосов
/ 28 декабря 2008
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 ]

4 голосов
/ 28 декабря 2008

Нет, нет более чистого пути. Использование Синтаксис 2 Select() и лямбда-выражения для применения Math.Log() к каждому элементу - идиоматический способ сделать это в C #.

2 голосов
/ 29 декабря 2008

Для полноты следует также отметить, что одним из самых больших недостатков Linq является возможность его расширения.

Если эта операция является чем-то, что вы делаете много, вполне возможно, что она поможет расширить ваш IEnumerable с помощью функции Log, это будет очень просто

  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();
2 голосов
/ 28 декабря 2008
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);
1 голос
/ 29 декабря 2008

В этом коде:

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

Большая часть, если не все, "Cruft", который вы видите, связана с использованием массивов, когда заголовок вопроса гласит: "Есть ли более чистый синтаксис для применения операции к каждому элементу последовательности * 1005?" *? "

В .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));

Как правило, новые функции C # 3.0 (особенно LINQ) наиболее эффективно воспроизводятся при использовании List <> вместо Arrays.

Если у вас есть код, уже основанный на массивах, я бы предложил добавить перегрузки к вашему API, которые принимают IEnumerable вместо int [], позволяя потребляющему коду использовать возможности современного языка.

1 голос
/ 28 декабря 2008

Это выглядит для меня самым чистым решением: -

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

Это должно быть лучшее решение, чем select, поскольку ConvertAll заранее знает, сколько элементов будет в возвращаемом массиве. Я не уверен, что это верно для select, это может быть, если происходит какая-то другая магия компилятора. Однако вышесказанное является более понятным, поскольку цель преобразования более ясна.

1 голос
/ 28 декабря 2008

Вы можете заключить уродство в функцию:

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
0 голосов
/ 28 декабря 2008

Не совсем уверен, что вы спрашиваете, но ...

Вы можете указать индекс в массиве.


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]);
            }

        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...