【问题标题】:Implement List of Objects Using Dictionary Key/Value Pair使用字典键/值对实现对象列表
【发布时间】:2017-09-26 09:58:55
【问题描述】:

我正在尝试使用 Dictionary<>List<> 进行搜索。我知道,我可以使用List<> 轻松做到这一点,如下所示:

var con = (from c in db.Customers
           where c.Status == status
           select c).ToList(); 

但首选并尝试使用Dictionary<> 实现上述功能。我的概念(我们都知道)是使用键/值会提高搜索选项的性能。这看起来很简单并且有点卡住了。这是我尝试过的:

static void Main(string[] args)
{
   Dictionary<string, Customer> custDictionary = new Dictionary<string, Customer>(); //Dictionary declared

   List<Customer> lst = new List<Customer>(); //List of objects declared

   Customer aCustomer = new Customer(); //Customer object created

   /**Assign values - Starts**/
   aCustomer.CustomerId = 1001;
   aCustomer.CustomerName = "John";
   aCustomer.Address = "On Earth";
   aCustomer.Status = "Active";

   aCustomer.CustomerId = 1002;
   aCustomer.CustomerName = "James";
   aCustomer.Address = "On Earth";
   aCustomer.Status = "Inactive";
   /**Assign values - Ends**/

   custDictionary.Add(aCustomer.Status, aCustomer); //Added to the dictionary with key and value

   string status = Console.ReadLine().ToUpper();

   if (custDictionary.ContainsKey(status)) //If key found in the dictionary
   {
      Customer cust = custDictionary[status];
      Console.WriteLine(cust.CustomerId + " " + cust.CustomerName); //Outputs the final result - Right now no result found here
   }

  Console.ReadKey();
}

public class Customer
{
   public int CustomerId { get; set; }
   public string CustomerName { get; set; }
   public string Address { get; set; }
   public string Status { get; set; }
}  

不幸的是,上面没有返回任何结果。我正在尝试通过传递状态键并再次传递Customer 对象作为值来获取客户详细信息。我不确定我在这里缺少什么。

还有一件事,在现实生活中的项目中,我们将数据库结果作为列表。所以在这种场景下,如果使用Dictionary&lt;&gt;,我相信数据库结果应该保持如下:

lst.Add(aCustomer); //As database will have more result or data simply

另一方面,我认为字典应该如下所示:

Dictionary<string, List<Customer>> custDictionary = new Dictionary<string, List<Customer>>();

我的问题 - 在字典中为键/值对传递对象列表是否是个好主意,我已经尝试过使用它。但是还没有得到输出。

注意:这听起来像是一个新手问题,是的。我已经尝试在网上搜索并仍在研究它。我很抱歉提出这样的问题,如果有更好的方法来做上述事情,我会期待一些答案。

【问题讨论】:

  • 不应该是您的字典键CustomerId?您当前正在添加状态。
  • 我正在尝试将密钥作为字符串 @krlzlx 传递。这会产生差异吗?
  • 如果您有多个具有相同状态的客户,您将收到重复错误。
  • 我知道了@krlzlx 并感谢它。

标签: c# asp.net list dictionary


【解决方案1】:

更新

如果要将它们存储在列表中,可以执行以下代码。要选择项目,您可以使用 Linq,这样您就不会遇到字典中重复值的问题:

        var lst = new List<Customer>(); //List of objects declared

        lst.AddRange(
            new List<Customer>() {
                new Customer()
                {
                    CustomerId = 1001,
                    CustomerName = "John",
                    Address = "On Earth",
                    Status = "Active"
                },
                new Customer()
                {
                    CustomerId = 1002,
                    CustomerName = "James",
                    Address = "On Earth",
                    Status = "Inactive"
                }
            }
        );

        var status = Console.ReadLine();
        var selected = lst.Where(x => x.Status.ToUpper() == status.ToUpper()).ToList();
        foreach (var item in selected)
        {
            Console.WriteLine(item.CustomerId + " " + item.CustomerName);
        }

更新 2

如果要将上述列表添加到字典中,可以如下操作:

var custDictionary = new Dictionary<string, List<Customer>>();

// the above code for the list

custDictionary.Add("keyname", lst);

原始答案

您只保存了一个客户,因为您正在用第二个客户覆盖第一个客户:

Dictionary<string, Customer> custDictionary = new Dictionary<string, Customer>();
List<Customer> lst = new List<Customer>();

// Add first customer
var aCustomer = new Customer()
{
    CustomerId = 1001,
    CustomerName = "John",
    Address = "On Earth",
    Status = "Active"
};
custDictionary.Add(aCustomer.Status.ToUpper(), aCustomer);

// Add second customer
var bCustomer = new Customer()
{
    CustomerId = 1002,
    CustomerName = "James",
    Address = "On Earth",
    Status = "Inactive"
};
custDictionary.Add(bCustomer.Status.ToUpper(), bCustomer);

您还需要将状态存储为大写,因为您正在检查状态是否以大写形式存在:

string status = Console.ReadLine().ToUpper();
if (custDictionary.ContainsKey(status)) //If key found in the dictionary
{
    Customer cust = custDictionary[status];
    Console.WriteLine(cust.CustomerId + " " + cust.CustomerName); //Outputs the final result - Right now no result found here
}

Console.ReadKey();

【讨论】:

  • 您还保存了相同的客户对象,只是在不同的键下。您所做的更改也会影响第一个值。它是相同的参考。
  • 更新了答案,也更简洁了
  • 好的。我希望弄清楚并感谢@Clive Ciappara。您已经创建了 Customer 类的两个实例并将它们添加到字典中。假设,如果我尝试将它们添加到 List&lt;&gt; 或从数据库表中获取对象列表并将它们作为值分配给字典。
  • 您想将它们添加到列表而不是字典中,对吗?该列表将只是一个客户列表?我将使用客户列表为您更新答案
  • 检查答案:我将字典更改为列表并选择项目,您可以使用Linq。这样,您就不会遇到字典中重复值的问题。而且更干净:)
【解决方案2】:

如果您已经拥有该列表并想创建一个Dictionary&lt;string, List&lt;Customer&gt;&gt;,您可以这样做:

Dictionary<string, List<Customer>> dict = 
        list.GroupBy(c=>c.Status.ToUpper()).ToDictionary(g => g.Key, g=> g.ToList());

并迭代它:

foreach (var customer in dict[status.ToUpper()])
{
}

但是,

我没有看到这样做的价值。如果您需要让所有具有特定状态的客户保留您所拥有的 - 一个简单的 linq 查询。

【讨论】:

  • 这就是我一直在寻找的东西,而你让它看起来如此简单。谢谢@Ofir Winegarten。我有两个问题。 1)您提供的上述内容和Linq,我想会有性能问题。我的意思是,它会比Linq 更快地工作。如果我错了,请纠正我,尽管它使用 foreach 循环。 2)我也使用了其他代码。当字典中有重复值时,它会抛出异常。但是有了上面的内容,它对于像现在有两个 ActiveInactive 状态值的重复项非常有效。
  • 不客气。关于您的问题: 1. 除非列表很大并且您多次执行 linq,否则转到字典是没有意义的。不要忘记它仍然必须将其从列表转换为字典。那有什么意义呢?第二个问题对我来说似乎更像是一个陈述,不是吗? :-)
  • 好的。知道了。感谢您的时间和精力。
【解决方案3】:

即使您将状态添加为键,您的代码也存在 2 个问题。

  1. 您需要创建 2 个对象来逐个创建 2 个客户。您只添加了一次客户,并分配了两次值。

  2. Console.ReadLine().ToUpper() - 删除 ToUpper(),因为您要添加大小写混合的值。如果你想这样做,用StringComparer.InvariantCultureIgnoreCase初始化字典。

这对你有用。

Dictionary<string, Customer> custDictionary = new Dictionary<string, Customer>(StringComparer.InvariantCultureIgnoreCase); //Dictionary declared

   List<Customer> lst = new List<Customer>(); //List of objects declared

   Customer aCustomer = new Customer(); //Customer object created

   /**Assign values - Starts**/
   aCustomer.CustomerId = 1001;
   aCustomer.CustomerName = "John";
   aCustomer.Address = "On Earth";
   aCustomer.Status = "Active";
   custDictionary.Add(aCustomer.Status, aCustomer); //Added to the dictionary with key and value

   Customer bCustomer = new Customer(); //Customer object created
   bCustomer.CustomerId = 1002;
   bCustomer.CustomerName = "James";
   bCustomer.Address = "On Earth";
   bCustomer.Status = "Inactive";


   custDictionary.Add(bCustomer.Status, bCustomer); //Added to the dictionary with key and value

   string status = Console.ReadLine().ToUpper();

   if (custDictionary.ContainsKey(status)) //If key found in the dictionary
   {
      Customer cust = custDictionary[status];
      Console.WriteLine(cust.CustomerId + " " + cust.CustomerName); //Outputs the final result - Right now no result found here
   }

  Console.ReadLine();

【讨论】:

  • 好的。谢谢@Amit。假设,如果我尝试将它们添加到 List 或从数据库表中获取对象列表并将它们作为值分配给字典,该怎么办。与此类似 - lst.Add(customer) 或从数据库表中检索数据。
  • 您可以在列表中使用 LINQ。 list.Where(t=&gt;t.Status == status) 进行搜索。在这种情况下,您需要将 string.Contains 与 FindAll 一起使用,如此处所示。 stackoverflow.com/a/5116205/7974050
  • 感谢您的努力,再次感谢@Amit。
【解决方案4】:

首先,您的字典键应该是 customerId 而不是 status。检查字典是否包含密钥将是一个好习惯,否则它会抛出异常已经添加了相同的密钥。所以最好检查然后在字典中执行添加或更新。

static void Main(string[] args)
{
   Dictionary<string, Customer> custDictionary = new Dictionary<string, Customer>(); //Dictionary declared

   List<Customer> lst = new List<Customer>(); //List of objects declared

   Customer aCustomer = new Customer(); //Customer object created

   /**Assign values - Starts**/
   aCustomer.CustomerId = 1001;
   aCustomer.CustomerName = "John";
   aCustomer.Address = "On Earth";
   aCustomer.Status = "Active";
   if (!custDictionary.ContainsKey(aCustomer.CustomerId))
        custDictionary.Add(aCustomer.CustomerId, aCustomer);
    else
        custDictionary[aCustomer.CustomerId] = aCustomer;

   aCustomer.CustomerId = 1002;
   aCustomer.CustomerName = "James";
   aCustomer.Address = "On Earth";
   aCustomer.Status = "Inactive";
   /**Assign values - Ends**/

   if (!custDictionary.ContainsKey(aCustomer.CustomerId))
        custDictionary.Add(aCustomer.CustomerId, aCustomer);
    else
        custDictionary[aCustomer.CustomerId] = aCustomer;


   string status = Console.ReadLine().ToUpper();

   if (custDictionary.ContainsKey(aCustomer.CustomerId)) //If key found in the dictionary
   {
      Customer cust = custDictionary[aCustomer.CustomerId];
      Console.WriteLine(cust.CustomerId + " " + cust.CustomerName); //Outputs the final result - Right now no result found here
   }

  Console.ReadKey();
}

【讨论】:

  • 感谢您的努力,再次感谢@Ravi Kanth。
【解决方案5】:

您没有得到任何输出,因为您将输入转换为大写,而您在 pascalcase 中插入了键,并且在 C# 集合的情况下,键区分大小写。这样您的输入与集合中的任何键都不匹配

将您的行号:29 更改为此代码

 string status = Console.ReadLine();

并从您的控制台插入“非活动”此密钥存在于您的集合中 所以你会想要的结果..

【讨论】:

  • 感谢您的努力,再次感谢@Saurabh Mishra。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多