Поворот массива с использованием синтаксиса LINQ - PullRequest
1 голос
/ 04 сентября 2010

Я решаю эту проблему вращения массива и получил алгоритм и код, работающий

 int[] Rotate(int[] ar,int k)
        {
            if (k <= 0 || k > ar.Length - 1)
                return ar;
            Reverse(ar, 0, k - 1);
            Reverse(ar, k, ar.Length - 1);
            Reverse(ar, 0, ar.Length - 1);
            return ar;            
        }

 void Reverse(int[] ar,int start, int end)
        {
            while (start < end)
            {
                int temp = ar[start];
                ar[start] = ar[end];
                ar[end] = temp;
                start++;
                end--;
            }
        }

Теперь я хочу сделать это в LINQ, и я получил следующий код, я думаю, что это можно сделать намного лучше,

 int[] Rotate(int[] ar,int k)
    {
        if (k <= 0 || k > ar.Length - 1)
            return ar;
        int[] ar1=ar.Take(k-1).Reverse().ToArray();
        int[] ar2=ar.Skip(k - 1).Take(ar.Length - k+1).Reverse().ToArray();
        int[] ar3 = ar1.Concat(ar2).Reverse().ToArray();
        return ar3;
    }

Это хорошо известный алгоритм из Programming pearls - http://books.google.com/books?id=kse_7qbWbjsC&lpg=PA14&ots=DfzTzQCSar&dq=rotate%20an%20array%20programming%20pearls&pg=PA14#v=onepage&q&f=false

И вообще, как развивать мои навыки LINQ, если у меня возникли проблемы с программированием, прямо сейчас ядумать только о циклах или циклах foreach, как думать с помощью операторов linq.Я читаю слова C # 4.0, кроме как практиковать какие-либо советы?

Ответы [ 3 ]

14 голосов
/ 04 сентября 2010

Я не уверен, почему у вас есть все развороты, если честно.Как насчет этого:

int[] Rotate(int[] ar,int k)
{
    if (k <= 0 || k > ar.Length - 1)
        return ar;
    return ar.Skip(k)            // Start with the last elements
             .Concat(ar.Take(k)) // Then the first elements
             .ToArray();         // Then make it an array
}

Вот короткая, но полная программа, чтобы продемонстрировать это:

using System;
using System.Linq;

class Test
{
    static int[] Rotate(int[] ar,int k)
    {
        if (k <= 0 || k > ar.Length - 1)
            return ar;
        return ar.Skip(k)            // Start with the last elements
                 .Concat(ar.Take(k)) // Then the first elements
                 .ToArray();         // Then make it an array
    }

    static void Main()
    {
        int[] values = { 1, 2, 3, 4, 5 };
        int[] rotated = Rotate(values, 3);

        Console.WriteLine(string.Join(", ", rotated));
    }
}

Вывод: 4, 5, 1, 2, 3

РЕДАКТИРОВАТЬЯ только что заметил одно существенное различие между моим кодом и вашим исходным кодом: ваш изменяет исходный массив - мой возвращает массив новый с повернутыми значениями.Как и ваш код LINQ, но это означает, что если бы вы тестировали мой код с чем-то, что смотрело только на исходный массив, вы бы не увидели поворота.

LINQ в целом предназначен для такой работы - этоодобряет возврат новой последовательности вместо изменения существующей.

3 голосов
/ 04 сентября 2010

Начиная с вашего кода:

int[] ar1=ar.Take(k-1).Reverse().ToArray(); 
int[] ar2=ar.Skip(k - 1).Take(ar.Length - k+1).Reverse().ToArray(); 
int[] ar3 = ar1.Concat(ar2).Reverse().ToArray(); 

Поскольку вы просто хотите получить все оставшиеся элементы, дубль во второй строке не требуется.

ar1 и ar2 просто перечислены, поэтому они не должны быть массивами. Вызовы ToArray не нужны. С небольшим количеством творческого переименования мы имеем:

IEnumerable<int> revFirst = ar.Take(k-1).Reverse(); 
IEnumerable<int> revLast = ar.Skip(k-1).Reverse(); 
int[] ar3 = revFirst.Concat(revLast).Reverse().ToArray(); 

Теперь у нас есть

rev (rev (первая) + rev (последняя))

Распределение внешнего оборота дает

rev (rev (последняя)) + rev (rev (первая))

, что совпадает с

last + first

применение тех же операций к коду дает

IEnumerable<int> first = ar.Take(k-1); 
IEnumerable<int> last = ar.Skip(k-1); 
int[] ar3 = last.Concat(first).ToArray(); 

, что еще больше упрощает до

int[] ar3 = ar.Skip(k-1).Concat(ar.Take(k-1)).ToArray(); 

и теперь у нас есть ответ Джона Скита, поэтому мы должны сделать.

0 голосов
/ 18 октября 2018

это мое решение

public int[] solution(int[] A, int K) {
        // write your code in C# 6.0 with .NET 4.5 (Mono)
        if (A.Length <= 1)
        {
            return A;
        }
        var rotate = K % A.Length;

        var leftSide = A.Length - rotate;
        var arr1 = A.AsParallel().Skip(leftSide).Take(rotate);
        var arr2 = A.AsParallel().Take(leftSide);

        return arr1.Concat(arr2).ToArray();
}

вы можете проверить мой github .У меня также есть несколько юнит-тестов для других случаев и других уроков и задач codidlity

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