简体   繁体   English

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

[英]c# : avoid branching while iterating on a dictionary

I have the below code in which i branch for each sample in a dictionary, is there a way either by using LINQ or any other method in which i can avoid branching -> may be a functional approach我有下面的代码,其中我为字典中的每个样本分支,有没有办法通过使用 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 UPD

What if i have other type of comprasion:如果我有其他类型的比较怎么办:

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

One option would be to create a list of Action s that you wish to perform, then execute them based on the index.一种选择是创建您希望执行的Action列表,然后根据索引执行它们。 This way your methods can be quite varied.这样,您的方法可以多种多样。 If you need to perform very similar actions for each option, then storing a list of values would be a better than storing Actions.如果您需要为每个选项执行非常相似的操作,那么存储值列表将比存储操作更好。

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

If you wanted to use a dictionary as your comment implies:如果您想使用字典,因为您的评论暗示:

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

For this concrete case you can introduce another map( Dictionary or an array, as I did):对于这个具体案例,您可以引入另一个映射( 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]);
}

As for actual code it highly depends on usecases and how you want to handle faulty situations.至于实际代码,它在很大程度上取决于用例以及您希望如何处理错误情况。

UPD UPD

It seems that if you will be using dictionary for your map there still will be some branching , but if you will not have misses branch prediction should take care of it.看来,如果您将为 map 使用字典,仍然会有一些分支,但如果您不会错过分支预测,则应该注意它。

So you have a Dictionary<string, int> .所以你有一个Dictionary<string, int> Every item in the dictionary is a KeyValuePair<string, int> .字典中的每一项都是KeyValuePair<string, int> I assume that the string is the name of the sample (identifier), and the int is a number that says something about the sample:我假设字符串是样本的名称(标识符),而 int 是一个数字,说明了样本的一些情况:

  • if the number equals 0 or 1, the sample is qualified as Passed;如果数字等于0或1,则样品合格;
  • if the number equals 2, then you call it Isolated如果数字等于 2,那么你称它为孤立的
  • if the number equals 3, then you call it Biased.如果这个数字等于 3,那么你称之为 Biased。

All higher numbers are not interesting for you.所有更高的数字对你来说都不有趣。

You want to group the samples in Passed / Isolated / Biased samples.您想将样本分组为通过/隔离/偏差样本。

Whenever you have a sequence of similar items and you want to make groups of items, where every element has something in common with the other elements in the group, consider using one of the overloads of Enumerable.GroupBy每当您有一系列相似的项目并且想要创建项目组时,其中每个元素与组中的其他元素都有共同点,请考虑使用Enumerable.GroupBy的重载之一

Let's first define an enum to hold your qualifications, and a method that converts the integer value of the sample into the enum:让我们首先定义一个枚举来保存您的资格,以及将样本的 integer 值转换为枚举的方法:

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

Ok, so you have your dictionary of samples, where every key is a name of the sample and the value is a number that can be converted to a SampleQualification.好的,所以你有了样本字典,其中每个键都是样本的名称,值是可以转换为 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(),
         });

The result is a sequence of items.结果是一系列项目。 Where every item has a property Qualification, which holds Passed / Isolated / Biased.每个项目都有一个属性 Qualification,它持有 Passed/Isolated/Biased。 Every item also has a list of samples that have this qualification.每个项目还有一个具有此资格的样品列表。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM