繁体   English   中英

在C#中从字典过滤键值

[英]Filtering a Key Value from a Dictionary in C#

我是C#的新手,目前正在尝试找出实现以下内容的最佳方法:

我有一个与相关群体的物种清单:

Bird: "Budgie", "Parrot"
Dog: "Pitbull", "Labrador"
Cat: "Cheetah", "Lion"

鉴于一串动物,我需要归还其组。 例如。 “猎豹”将归还“猫”。

我已经实现了以下内容:

// create list one and store values
List<string> valSetOne = new List<string>();
valSetOne.Add("Budgie");
valSetOne.Add("Parrot");

// create list two and store values
List<String> valSetTwo = new List<String>();
valSetTwo.Add("Lion");
valSetTwo.Add("Cheetah");

// create list three and store values
List<String> valSetThree = new List<String>();
valSetThree.Add("Labrador");
valSetThree.Add("Pitbull");

// add values into map
map.Add("Bird", valSetOne);
map.Add("Cat", valSetTwo);
map.Add("Dog", valSetThree);

foreach(KeyValuePair<string, List<string>> kvp in map){
    foreach(string value in kvp.Value)
    {
       Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, value);
    }
}

而不是有一个foreach循环,有没有更快的方法来找到给定动物值的关键?

//编辑:

目前正在尝试使用元组进行初始化

var tupleList = new List<Tuple<string, List<string>>>
{
   new Tuple<string, List<string>>("cat", { "cheetah", "lion"})

};

我收到以下错误:意外符号`{'

如果您不想使用其他方式存储数据并将其存储在带有动物种类键的字典中,我建议您将与每个键关联的值的类型更改为HashSet

Dictionary<string, HashSet<string>>

这样做你可以遍历字典的键( O(n) ,其中n是键的数量),并使用O(1) HashSet Contains方法,你可以找出动物是否与当前键/ spiece相关联或不。

对数据进行更好的建模将是创建一个具有名称和动物集合的群组。 然后,您可以保存一组组并进行查询。

如果你想坚持使用字典:那么你的问题是从该keyvalue列表中检索给定value的键,我会以相反的方式组织数据:

var map = new Dictionary<string,string>
{
    ["Cheetah"] = "Cat",
    ["Lion"] = "Cat",
    //....
};

然后你可以用真正的钥匙搜索 - 这是物种而不是群体:

if(map.TryGetValue("Lion", out var group)) { }

由于通过分组到物种列表来构建数据更容易,您可以:

var rawData = new List<(string group, List<string> species)>
{
    ("Cat", new List<string> { "Cheetah", "Lion" }),
    //...
};

var result = rawData.SelectMany(item => item.species.Select(s => (s, item.group)))
                    .ToDictionary(k => k.s, v => v.group);

这适用于名为元组的C#7.0。 如果您使用的是以前的版本,则可以使用匿名类型或“旧时尚”元组

对于集合的预C#7.0初始化:

var rawData = new List<Tuple<string, List<string>>>
{
    Tuple.Create<string,List<string>> ("Cat", new List<string> { "Cheetah", "Lion" })
};

使用现有的字典结构,您可以这样做:

string cheetahGroup = map.FirstOrDefault(item => 
    item.Value.Contains("cheetah", StringComparer.OrdinalIgnoreCase)).Key;

请注意,如果动物不存在,那么cheetahGroup将为null 在上面的例子中,它将是"Cat"

正如其他人所说,我认为你应该在这里使用课程。 但其他反应停在1级课程。 我建议采用更全面的面向对象方法。

public abstract class Animal {}

public abstract class Dog : Animal {}
public abstract class Cat : Animal {}
public abstract class Bird : Animal {}

public sealed class Budgie : Bird {}
public sealed class Parrot : Bird {}
public sealed class Pitbull : Dog {}
public sealed class Labrador : Dog {}
public sealed class Cheetah : Cat {}
public sealed class Lion : Cat {}

[注意密封在这里是可选的]

那你就说

Labrador spot = new Labrador();

检查它是否是一只狗

if (spot is Dog) {
    print("it's a dog");
}

该解决方案可选择易于扩展,并且易于阅读。 没有奇怪的代码会分散你的注意力,因为拉布拉多犬是一只狗,而鹦鹉是一只鸟。 很清楚你要做什么以及Dog,Cat,Cheetah等代表什么类。

如果你想进一步将拉布拉多分为巧克力色,黄色和黑色,你可以添加另一层从拉布拉多继承的类。 如果你需要定义动物的属性,这也很容易。 例如,如果您只想让Dogs和Cats拥有名称,则可以在其类中添加名称字段,而如果您希望所有动物都有名称,则可以将名称字段放在Animal类中。

如果您需要移动动物,您可以在动物级别定义一个名为Move()的方法,强制其子项以自己的方式覆盖此方法,因此也许狗会通过Walking()移动(),而鸟类会移动()飞行()。

我会认真地建议放弃字典并考虑使用与我所描述的类似的东西。 如果你开始这么想,它将真正帮助你规划更复杂的项目和任务。 面向对象编程是如此普遍的原因!

我会制作一个Animal类,因为你正在使用动物,这将有两个属性: SpeciesSubSpecies

public class Animal
{
    public string Species { get; set; }
    public string SubSpecies { get; set; }

    public Animal(string Species, string SubSpecies)
    {
        this.Species = Species;
        this.SubSpecies = SubSpecies;
    }
}

然后你可以在列表中实现所有动物:

List<Animal> myAnimals = new List<Animal>();
myAnimals.Add(new Animal("Bird", "Budgie"));
myAnimals.Add(new Animal("Bird", "Parrot"));
myAnimals.Add(new Animal("Dog", "Pitbull"));
myAnimals.Add(new Animal("Dog", "Labrador"));
myAnimals.Add(new Animal("Cat", "Cheetah"));
myAnimals.Add(new Animal("Cat", "Lion"));    

最后,您可以使用Linq查找您要查找的内容:

//Will return null if the subSpecies doesn't exist
public string FindTheSpecies(string SubSpecies)
{
    return myAnimals.FirstOrDefault(x => x.SubSpecies == SubSpecies)?.Species;
}

暂无
暂无

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

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