这是一个基本问题(我是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());
}
}
谢谢大家的帮助!
答案 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;
}