C#:避免在字典上迭代时分支

时间:2020-05-18 18:21:28

标签: c# linq

我有以下代码,其中i为字典中的每个样本分支,有没有一种方法可以通过使用LINQ或其他任何可以避免分支的方法->可能是一种功能性方法

Dictionary<string, int> samples = new Dictionary<string, int>()
{
    {"a", 1},
    {"aa", 2},
    {"b", 1},
    {"bb", 3}
};

foreach (var sample in samples)
{
    if (sample.Value ==)
    {
        Console.WriteLine("sample passed");
    }
    else if (sample.Value == 2)
    {
        Console.WriteLine("sample isolated");
    }
    else if (sample.Value == 3)
    {
        Console.WriteLine("sample biased");
    }
}

UPD

如果我有其他类型的夸张该怎么办?

foreach (var sample in samples)
{
    if (sample.Value <= 1)
    {
        Console.WriteLine("sample passed");
    }
    else if (sample.Value <= 2)
    {
        Console.WriteLine("sample isolated");
    }
    else if (sample.Value <= 3)
    {
        Console.WriteLine("sample biased");
    }
}

3 个答案:

答案 0 :(得分:0)

一个选择是创建要执行的Action列表,然后根据索引执行它们。这样,您的方法就可以多种多样。如果您需要为每个选项执行非常相似的操作,那么存储值列表会比存储操作更好。

List<Action> functions = new List<Action>();
functions.Add(() => Console.WriteLine("sample passed"));
functions.Add(() => Console.WriteLine("sample isolated"));
functions.Add(() => Console.WriteLine("sample biased"));

foreach (var sample in samples)
{
  Action actionToExecute = functions[sample.Value - 1];
  actionToExectute();
}

如果您想使用字典作为注释,则表示:

Dictionary<int, Action> functions = new Dictionary<int, Action>();
functions.Add(1, () => Console.WriteLine("sample passed"));
functions.Add(2, () => Console.WriteLine("sample isolated"));
functions.Add(3, () => Console.WriteLine("sample biased"));

foreach (var sample in samples)
{
  Action actionToExecute = functions[sample.Value];
  actionToExectute();
}

答案 1 :(得分:0)

对于这种具体情况,您可以引入另一个映射(像我一样{Dictionary或数组):

Dictionary<string, int> samples = new Dictionary<string, int>()
            {
                {"a", 1},
                {"aa", 2},
                {"b", 1},
                {"bb", 3}
            };

var map = new []
{
    "sample passed",
    "sample isolated",
    "sample biased"
};
foreach (var sample in samples)
{
    Console.WriteLine(map[sample.Value - 1]);
}

对于实际代码,它很大程度上取决于用例以及您要如何处理错误情况。

UPD

看来,如果您仍要在地图上使用字典,will be some branching还是不错的选择,但是如果您不会错过任何机会,分支预测应该解决这一问题。

答案 2 :(得分:0)

因此,您有一个Dictionary<string, int>。字典中的每个项目都是KeyValuePair<string, int>。我假设字符串是样本(标识符)的名称,而int是表示样本内容的数字:

  • 如果数字等于0或1,则样本合格为合格;
  • 如果数字等于2,则将其称为“孤立的”
  • 如果数字等于3,则称其为“有偏差”。

所有更高的数字对您来说都不有趣。

您要将样本分为“通过” /“隔离” /“有偏”样本。

每当您有一系列相似的项目并且想要组成一组项目时,其中每个元素与该组中的其他元素都有一些共同之处,请考虑使用Enumerable.GroupBy

让我们首先定义一个枚举来保存您的资格,以及一个将样本的整数值转换为枚举的方法:

enum SampleQualification
{
    Passed,
    Isolated,
    Biased,
}

SampleQualification FromNumber(int number)
{
    switch (number)
    {
        case 2:
            return SampleQualification.Isolated;
        case 3:
            return SampleQualification.Biased;
        default:
            return SampleQualification.Passed;
    }
}

好,因此您有样本字典,其中每个键都是样本的名称,值是可以转换为SampleQualification的数字。

Dictionary<string, int> samples = ...
var qualifiedSamples = samples // implements IEnumerable<KeyValuePair<string, int>>

    // keep only samples with Value 0..3
    .Where(sample => 0 <= sample.Value && sample.Value <= 3)

    // Decide where the sample is Passed / Isolated / Biased
    .Select(sample => new
    {
        Qualification = FromNumber(sample.Value)
        Name = sample.Key,           // the name of the sample
        Number = sample.Value,

    })

    // Make groups of Samples with same Qualification:
    .GroupBy(
        // KeySelector: make groups with same qualification:
        sample => sample.Qualification,

        // ResultSelector: take the qualification, and all samples with this qualification
        // to make one new:
        (qualification, samplesWithThisQualification) => new
        {
            Qualification = qualification,
            Samples = samplesWithThisQualification.Select(sample => new
            {
                Name = sample.Name,
                Number = sample.Number,
            })
            .ToList(),
         });

结果是一系列项目。每个项目都具有财产资格,该资格持有通过/隔离/有偏。每个项目还包含具有此资格的样品列表。

// Process Result
foreach (var qualifiedSample in qualifiedSamples)
{
    Console.WriteLine("All samples with qualification " + qualifiedSample.Qualification);
    foreach (var sample in qualifiedSample.Samples)
    {
        Console.WriteLine({0} - {1}, sample.Name, sample.Value);
    }
}