我需要数组索引迭代的正模

本文关键字:迭代 索引 数组 | 更新日期: 2023-09-27 18:21:57

我有一个由字符串{"a", "b", "c", "d", "e"}组成的列表List A。我的程序在迭代中运行,每次迭代我都想创建一个新的列表List B,它将包含相同的字符串,但每个字符串都应该移动到左侧的一个位置。以下是List B在前三次迭代中应该是什么样子的示例:

  1. 迭代,列表B应该是:listB = {"a", "b", "c", "d", "e"}
  2. 迭代,列表B应该是:listB = {"b", "c", "d", "e", "a"}
  3. 迭代,列表B应为: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的公式吗?谢谢

我需要数组索引迭代的正模

这是一种非常复杂的工作方式,而且它实际上根本不起作用,尤其是在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,则函数返回原始列表。

我在这里实现了这一点: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

尝试

int order = ((j - iterationNum) % listACount + 1);
if (order < 0) order += listACount + 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));

好的,第二次尝试:

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

下面是一些代码,我把它们拼凑在一起,以获得更好的运行时。它适用于包含的单元测试,如果我第一次没有准确地确定它,你可以从那里进行调整。。。

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