循环遍历两个列表

时间:2018-03-15 18:31:17

标签: c# .net loops

请原谅我的愚蠢我不认为我的咖啡已经踢了:(

我正在尝试遍历两个列表,并根据两个列表的值创建一个赋值。 例如。 列表1是我要创建的文件夹列表 清单2是具有可用空间的硬盘驱动器列表

我希望通过列表计数在驱动器上传播文件夹创建不相等。

所以我想让对于文件夹列表中的第一次迭代尝试驱动器1,如果它有空间并且还没有文件夹创建它。 然后移动到文件夹2并驱动两个 - 然后驱动器三和驱动器三(如果驱动器的总数是3)我想移回驱动一个用于下一个文件夹,直到创建所有文件夹。

任何人都可以帮我提供如何到达那里的样本吗?

2 个答案:

答案 0 :(得分:2)

我经常考虑的问题是"我怎样才能将棘手的机制转移到他们自己的类型上?#34;。在你的情况下,你想要一个列表的枚举,它在完成时重新开始,但另一种思考方式是让一个计数器在到达范围顶部时回绕。所以,让我们实现:

struct WrappingCounter
{
    private int current;
    private int max;
    public WrappingCounter(int max) : this(0, max) {
        if (max <= 0) throw new ArgumentException();
    }
    private WrappingCounter(int current, int max)
    {
        this.current = current % max;
        this.max = max;
    }
    public static implicit operator int(WrappingCounter c) {
        return c.current;
    }
    public static WrappingCounter operator ++(WrappingCounter c) {
        return new WrappingCounter(c.current + 1, c.max);
    }
}

这段代码也很有趣,因为它是如何在C#中编写正确的++运算符的对象课程。请注意++ 返回递增值,与C ++不同。它不会改变c;它会生成一个 new 对象,表示递增的c。编译器将在适当的时候进行分配。

现在我们已经将丑陋的机制分离到了他们自己的类型,现在主要的算法变得更容易阅读:

var dirs = new List<string> { "dir1", "dir2", "dir3" };
var drives = new List<string> { "drive1", "drive2" };
var c = new WrappingCounter(drives.Count);
foreach(var dir in dirs) {
    var drive = drives[c];
    c++;
    Console.WriteLine(dir + " " + drive);
}

答案 1 :(得分:0)

以下是算法的概要。它将第一个文件夹与第一个驱动器匹配,第二个文件夹与第二个驱动器匹配,依此类推。除非没有足够的空间。然后它将尝试后续驱动器(在循环中)。一旦找到空间,它将在找到最后一个之后继续在驱动器上进行迭代。例如:

folder_1 - &gt; drive_a
folder_2 - &gt; drive_b
folder_3 - &gt; (skip drive_c) - &gt; drive_d
folder_4 - &gt; drive_e

// You'll need to associate required space with each folder
public class FolderThing
{
    public string Name {get; set;}
    public int Size {get; set;}
}

// Each drive will need to track available free space
public class DriveThing
{
    public string Name {get; set;}
    public int AvailableSpace {get; set;}
}

// Collection of folders, populate as required.
var foldersToAllocate = new List<FolderThing>();

// Collection of drives, populate as required.
var drivesToUse = new List<DriveThing>();

var numberOfDrives = drivesToUse.Count();
int nextDrive = 0;

foreach (var f in foldersToAllocate)
{
    // Track whether space could be allocated ...
    bool spaceFound = false;
    int tryCount = 0;

    // For loop, to exit early on success.
    // Try every available drive once, until space is found.
    for (tryCount=0; tryCount<numberOfDrives; tryCount++)
    {
        var drive = drivesToUse[(tryCount + nextDrive) % numberOfDrives];

        if (drive.AvailableSpace > f.Size)
        {
            // do the allocate thing
            // update space used for drive
            spaceFound = true;
            break;
        }
    }

    // Increment to the next drive after the previous one.
    nextDrive = (nextDrive + tryCount + 1) % numberOfDrives;

    if (spaceFound == false)
    {
        throw new Exception("Could not find enough free space");
    }

}