我有一个由List A
字符串组成的列表{"a", "b", "c", "d", "e"}
。
我的程序在迭代中运行,并且对于每次迭代,我想创建一个新列表List B
,它将包含相同的字符串,但每个应该移动到左边的一个位置。以下是前三次迭代中List B
应该是什么样子的示例:
listB = {"a", "b", "c", "d", "e"}
listB = {"b", "c", "d", "e", "a"}
listB = {"c", "d", "e", "a", "b"}
我已通过以下方法实现了所需的功能:
private List<string> CalculateQueueOrder(List<string> listA, int iterationNum)
{
int listACount = listA.Count;
List<string> listB = new List<string>();
for (int i = 0; i < listACount; i++)
{
for (int j = 0; j < listACount; j++)
{
int order = ((j - iterationNum) % listACount + 1);
if (order == i)
{
string listItem = listA[j];
listB.Add(listItem);
break;
}
}
}
return listB;
}
但是,此方法存在问题。随着迭代次数的增加,j - iterationNum
开始返回负值,这使得模数也开始返回负值。整个功能失败了。我需要使模数始终返回正值,就像在Microsofot Excel(mod函数)中一样。
你能帮我修一下int order
的公式吗?谢谢。
答案 0 :(得分:3)
这是完成这项工作的一种错综复杂的方式,它实际上根本不起作用,不仅仅是当iterationNum太大时。这应该有所帮助:
int order = ((listACount + j - iterationNum % listACount + 1) % listACount);
更简单的方法,以防万一:
private List<string> CalculateQueueOrder(List<string> list, int iterationNum) {
iterationNum = (iterationNum - 1) % list.Count;
return list.Skip(iterationNum).Concat(list.Take(iterationNum)).ToList();
}
两种方法都假设迭代从1开始,而不是0,即如果iterationNum等于1,则函数返回原始列表。
答案 1 :(得分:1)
尝试
int order = ((j - iterationNum) % listACount + 1);
if (order < 0) order += listACount + 1;
快速修复。虽然我会尝试重写该方法,但这种双循环应该是不必要的。
答案 2 :(得分:1)
你的解决方案是O(N ^ 2),而它可以在O(N)时间内解决:
int iterationNumber = 2 % listA.Count; // substitute 2 with whatever number you want
List<string> listA = new List<string> { "a", "b", "c", "d", "e", "f" };
var listB = listA.Skip(iterationNumber).Concat(listA.Take(iterationNumber));
答案 3 :(得分:1)
我在这里实现了这个目标:http://rextester.com/HXACA68585
方法是:
private static IEnumerable<T> Cycle<T>(List<T> data, int num)
{
var start = num%data.Count;
for(var i=0;i<data.Count;i++)
{
yield return data[(i+start)%data.Count];
}
}
如果您愿意,可以将其重新列入新列表:
List<string> list = new List<string>(){"a", "b", "c", "d", "e"};
List<string> newList = new List<string>(Cycle(list,2)); // contains c, d, e, a, b
但要测试您所需的结果,请使用:
List<string> list = new List<string>(){"a", "b", "c", "d", "e"};
Dump(Cycle(list,0));
Dump(Cycle(list,1));
Dump(Cycle(list,2));
Dump(Cycle(list,3));
Dump(Cycle(list,4));
Dump(Cycle(list,5));
Dump(Cycle(list,6));
输出如下:
a, b, c, d, e
b, c, d, e, a
c, d, e, a, b
d, e, a, b, c
e, a, b, c, d
a, b, c, d, e
b, c, d, e, a
答案 4 :(得分:1)
var orglist = new List<string>() { "a", "b", "c", "d", "e" };
foreach (var list in CalculateQueueOrder(orglist))
{
Console.WriteLine(String.Join(" ",list));
}
IEnumerable<List<string>> CalculateQueueOrder(List<string> list)
{
//yield return list; //if you need the original list
for (int i = 0; i < list.Count-1; i++)
{
var newList = new List<string>(list.Skip(1));
newList.Add(list.First());
list = newList;
yield return newList;
}
}
答案 5 :(得分:1)
好的,第二次尝试:
public List<string> CalculateQueueOrder(List<string> list, int shift) {
int len = list.Count;
int start = shift % len;
List<string> newList = new List<string>();
for (int i = start; i < len; ++i) {
newList.Add(list[i]);
}
for (int i = 0; i < start; ++i) {
newList.Add(list[i]);
}
return newList;
}
答案 6 :(得分:0)
这是一些我用更好的运行时间编写的代码。它适用于包含的单元测试,如果我没有在第一次完全确定它,你可以从那里进行调整...
[TestClass]
public class ScratchPadTest
{
private int CalculateShift(int listCount, int iterations)
{
if (listCount == 0)
{
return 0;
}
return iterations % listCount;
}
private List<string> PerformShift(List<string> list, int iterations)
{
var myShiftCount = CalculateShift(list.Count, iterations);
var myList = new List<string>();
for (int index = 0; index < myShiftCount; index++)
{
myList.Add(list[(index + myShiftCount) % list.Count]);
}
return myList;
}
[TestMethod, Owner("ebd"), TestCategory("Proven"), TestCategory("Unit")]
public void ZeroIterationsReturns0()
{
Assert.AreEqual<int>(0, CalculateShift(0, 0));
}
[TestMethod, Owner("ebd"), TestCategory("Proven"), TestCategory("Unit")]
public void OneITerationReturnsOne_With_List_Size_Two()
{
Assert.AreEqual<int>(1, CalculateShift(2, 1));
}
[TestMethod, Owner("ebd"), TestCategory("Proven"), TestCategory("Unit")]
public void OneIterationReturns_Zero_With_ListSizeOne()
{
Assert.AreEqual<int>(0, CalculateShift(1, 1));
}
[TestMethod, Owner("ebd"), TestCategory("Proven"), TestCategory("Unit")]
public void Shifting_Two_Element_List_By_101_Reverses_Elements()
{
var myList = new List<string>() { "1", "2" };
Assert.AreEqual<string>("2", PerformShift(myList, 101)[0]);
}
}