将第一个数组元素移动到C#结束

时间:2018-03-26 14:57:38

标签: c# arrays

这是一个基本问题(我是C#的新手),但是有一种有效的方法可以将第一个元素移动到C#中的数组末尾吗?

我找到this question,它描述了ruby中的.rotate方法,但我无法在C#中找到类似的方法。

如果我有一个数组:

[1, 2, 3, 4, 5]

C#中是否有一个函数返回:

[2, 3, 4, 5, 1]

提前致谢!

编辑:回答

最好的解决方案是尽可能多地使用LinkedList<T>,如Alex's answer所示。他建议的解决方案是使用:

list.AddLast(list.RemoveFirst());

可以在 for循环中运行:

    void func<T>(LinkedList<T> list, int rotate) {
    for(var i = 0; i < rotate; i++) {
       list.AddLast(list.RemoveFirst());
    }
}

谢谢大家的帮助!

8 个答案:

答案 0 :(得分:7)

有很多方法可以实现这一目标。一种方法是:

var result = arr.Skip(1).Concat(arr.Take(1))

答案 1 :(得分:6)

如果您使用LinkedList<T>代替array<T>,则可以使用此代码:

list.AddLast(list.RemoveFirst());

复杂性O(1)。多次执行此操作时:

void func<T>(LinkedList<T> list, int rotate) {
    for(var i = 0; i < rotate; i++) {
       list.AddLast(list.RemoveFirst());
    }
}

您的复杂度为O(N) [其中N是转数]。这是性能方面的最佳解决方案。

如果你真的需要使用数组,这可能是一个天真的解决方案:

var tmp = list[0];
for(var i = 1; i < list.Length; i++) {
   list[i - 1] = list[i];
}
list[list.Length - 1] = tmp;

(请注意,没有范围检查)

但如果您经常需要这样做,这将非常耗时。如果您多次执行此操作:

void func<T>(T[] list, int rotate) {
    for(var j = 0; j < rotate; j++) {
       var tmp = list[0];
       for(var i = 1; i < list.Length; i++) {
           list[i - 1] = list[i];
       }
       list[list.Length - 1] = tmp;
    }
}

您最终会得到O(N^2) = O(N * M) [其中N是元素数量,M是轮换数量。这真的很糟糕。一个更好的方法,如果你事先知道你会经常这样做:

void func<T>(T[] list, int rotate {
    for(var j = 0; j < list.Length; j++) {
        var tmp = list[j];
        var ix = (rotate + j) % list.Length;
        list[j] = list[ix];
        list[ix] = tmp;
    }
}

这将导致O(N) [其中N是元素数量。)

正如其他人已经建议的那样,如果您需要在多个位置使用此扩展方法,最好编写一个扩展方法。

答案 2 :(得分:4)

使用Array.Copy将元素复制到自身只是移位;)

var array = new int[]{1, 2, 3, 4, 5};

var head = array[0];
Array.Copy(array, 1, array, 0, array.Length- 1);
array[array.Length - 1] = head;

作为返回新数组的扩展方法just like the Ruby version

static class ArrayRotateExtensions {
    public static int[] Rotate(this int[] arr, int offset) {
        var l = arr.Length;
        var rot = new int[l];

        if (offset == 0) {
            Array.Copy(arr, 0, rot, 0, l);
            return rot;
        }

        // constrain rotations greater than array length, it's the same result anyway
        offset = offset % l;

        // negative rotation is equal to positive rotation length - offset
        if (offset < 0) {
            offset += l;
        }

        Array.Copy(arr, offset, rot, 0, l - offset);
        Array.Copy(arr, 0, rot, l - offset, offset);

        return rot;
    }
}

这将允许你做

var array = new int[]{1, 2, 3, 4, 5};
var rotated = array.Rotate(1);

加上任意数量的旋转。

唯一的缺点是你必须为你想要使用它的每种阵列类型添加一个版本。

答案 3 :(得分:3)

现在开始看起来像Code Golf :-)所以这是我的贡献:

var x = new[] { 1, 2, 3, 4, 5 };

var y = Enumerable.Range(1, x.Length).Select(i => x[i % x.Length]).ToArray();

答案 4 :(得分:2)

LINQ中没有这样的功能的原因很可能是那些开​​发LINQ的人并不认为这是绝对必须的......

如果您确实需要,可以创建扩展方法。 有点像:

    public static IEnumerable<T> Rotate<T>(this IEnumerable<T> elements, int number)
    {
        var elemetsList = elements as IList<T> ?? elements.ToList();
        var list = new List<T>(elemetsList.Count);

        if (number > elemetsList.Count - 1)
        {
            throw new ArgumentException(nameof(number));
        }

        for (int i = number; i < elemetsList.Count; i++)
        {
            list.Add(elemetsList[i]);
        }

        for (int i = 0; i < number; i++)
        {
            list.Add(elemetsList[i]);
        }

        return list;
    }

并使用它:

var arr = new int[] {1, 2, 3, 4, 5};
int[] result = arr.Rotate(1).ToArray();
int[] result2 = arr.Rotate(3).ToArray();

输出:

2 3 4 5 1

4 5 1 2 3

此解决方案相当有效。 对于长度为500 000的阵列,我的机器只需要7毫秒即可执行。

答案 5 :(得分:2)

也许是这样 -

        static void Main( string[] args ) {
            Console.WriteLine(string.Join(", ", getArray(new int[] { 1, 2, 3, 4, 5 })));
            Console.Read();
            return;
        }
        static int[] getArray( int[] arr ) {
            List<int> O = new List<int>();
            for (int x = 1, l = arr.Length; x < l; x++) {
                O.Add(arr[x]);
            }
            O.Add(arr[0]);
            return O.ToArray();
        }

答案 6 :(得分:2)

试试这个..

using System;

public class Program
{   
    public static  int[] arrData = new int[5]{1,2,3,4,5};

    public static void Main()
    {
        Console.WriteLine("\nOriginal array\n");
        foreach(var item in arrData)
        {
            Console.WriteLine(item.ToString());
        }
        Console.WriteLine("\nShift to last\n");
        arrData = shiftLast(arrData);
        foreach(var item in arrData)
        {
            Console.WriteLine(item.ToString());
        }
    }

    public static int[] shiftLast(int[] arr)
    {
        int last = arr[arr.Length - 1];
        int first= arr[0];
        arr[arr.Length - 1] = first;
        arr[0] = last;
        return arr;
    }
}

尝试运行here

干杯

答案 7 :(得分:1)

据我所知,阵列没有这种方法。如果您经常这样做,也许您应该考虑使用其他对象(var AWSregion = 'us-east-1'; // us-east-1 var AWS = require('aws-sdk'); var dbClient = new AWS.DynamoDB.DocumentClient(); AWS.config.update({ region: "'us-east-1'" }); let GetMachineStateIntent = (context, callback) => { var params = { TableName: "updatedincident", Key: { date: "2018-03-28", time: "04:23", } }; dbClient.get(params, function (err, data) { if (err) { // failed to read from table for some reason.. console.log('failed to load data item:\n' + JSON.stringify(err, null, 2)); // let skill tell the user that it couldn't find the data sendResponse(context, callback, { output: "the data could not be loaded from your database", endSession: false }); } else { console.log('loaded data item:\n' + JSON.stringify(data.Item, null, 2)); // assuming the item has an attribute called "incident".. sendResponse(context, callback, { output: data.Item.incident, endSession: false }); } }); }; function sendResponse(context, callback, responseOptions) { if(typeof callback === 'undefined') { context.succeed(buildResponse(responseOptions)); } else { callback(null, buildResponse(responseOptions)); } } function buildResponse(options) { var alexaResponse = { version: "1.0", response: { outputSpeech: { "type": "SSML", "ssml": `<speak><prosody rate="slow">${options.output}</prosody></speak>` }, shouldEndSession: options.endSession } }; if (options.repromptText) { alexaResponse.response.reprompt = { outputSpeech: { "type": "SSML", "ssml": `<speak><prosody rate="slow">${options.reprompt}</prosody></speak>` } }; } return alexaResponse; } exports.handler = (event, context, callback) => { try { var request = event.request; if (request.type === "LaunchRequest") { sendResponse(context, callback, { output: "welcome to my skill. what data are you looking for?", endSession: false }); } else if (request.type === "IntentRequest") { let options = {}; if (request.intent.name === "GetMachineStateIntent") { GetMachineStateIntent(context, callback); } else if (request.intent.name === "AMAZON.StopIntent" || request.intent.name === "AMAZON.CancelIntent") { sendResponse(context, callback, { output: "ok. good bye!", endSession: true }); } else if (request.intent.name === "AMAZON.HelpIntent") { sendResponse(context, callback, { output: "you can ask me about incidents that have happened", reprompt: "what can I help you with?", endSession: false }); } else { sendResponse(context, callback, { output: "I don't know that one! please try again!", endSession: false }); } } else if (request.type === "SessionEndedRequest") { sendResponse(context, callback, ""); // no response needed } else { // an unexpected request type received.. just say I don't know.. sendResponse(context, callback, { output: "I don't know that one! please try again!", endSession: false }); } } catch (e) { // handle the error by logging it and sending back an failure console.log('Unexpected error occurred in the skill handler!', e); if(typeof callback === 'undefined') { context.fail("Unexpected error"); } else { callback("Unexpected error"); } } };List<T>等)。

但即使使用数组,您也可以使用extension methods实现这样的简单功能:

Stack<T>

然后使用只是:

public static int[] MoveFirstToLast (this int[] obj)
{
    int movedValue = obj[0];
    (int i = 1; i < obj.Length; i++)
    {
        obj[i - 1] = obj[i];
    }
    obj[obj.Length - 1] = movedValue;
    return obj;
}