0

I am trying to work with Dictionary<> along with List<> for searching purpose. I know, I can do this easily with List<> as follows:

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

But preferred and tried to implement the above with Dictionary<>. My concept (We all know that) is using the key/value will increase the search option performance. This looks simple and stuck a bit. Here what I've tried:

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

Unfortunately, the above doesn't return any result. What I am trying is to get customer details by passing status key and again passed Customer object as the value. I am not sure what I am missing here.

One more thing, in real-life projects, we get database results as list. So in this scenario, if Dictionary<> is used, I believe, the database results should be kept as follows:

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

On the other hand, I believe, the dictionary should look like the below:

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

My question - Is it a good idea to pass a list of objects in the dictionary for the key/vale pair and I've tried using so. But didn't get the output yet.

Note: This sounds like a novice question and yes, it's. I've tried to search online and still studying it. I apology to ask such a question and would expect some answers if there are any better ways to do the above.

AT-2017
  • 3,114
  • 3
  • 23
  • 39

5 Answers5

2

UPDATED

If you want to store them in a list, you can do the following code. To select the items, you can then use Linq, and in this way you don't have the issue of duplicate values in a dictionary:

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

UPDATE 2

If you want to add the above list in a dictionary, you can do as follows:

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

// the above code for the list

custDictionary.Add("keyname", lst);

ORIGINAL ANSWER

You are saving one customer only since you are overwriting the first customer with the second one:

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

Also you need to store the Status as uppercase, since you are checking if the status exist in uppercase:

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
  • 558
  • 5
  • 11
  • 1
    You are also saving the same customer object, only under a different key. The changes you are making also effect the first value. its the same reference. – Martin Backasch Sep 26 '17 at 10:14
  • Updated the answer, made it a bit cleaner as well – Clive Ciappara Sep 26 '17 at 10:18
  • OK. I am hoping to figure it out and thanks for it @Clive Ciappara. You have created two instances of the `Customer` class and added them to the dictionary. Suppose, what if I try to add those in a `List<>` or get list of objects from database table and assign them to the dictionary as value. – AT-2017 Sep 26 '17 at 10:23
  • You want to add them in a List instead of a dictionary right? And the list will be just a list of customers? I will update the answer for you with a list of customers – Clive Ciappara Sep 26 '17 at 10:28
  • Check the answer: I changed the dictionary to a list and to select the items, you can use Linq. In this way you don't have the issue of duplicate values in a dictionary. And it's cleaner :) – Clive Ciappara Sep 26 '17 at 10:33
  • If this is so, then in my opinion, it's useless to use dictionary and better to go with Linq/List. Seems like it isn't possible to assign `List<>` as value in `Dictionary`. May be I am wrong. – AT-2017 Sep 26 '17 at 10:37
  • If you want to add a list in the dictionary, you have to do something like this: var custDictionary = new Dictionary>(); – Clive Ciappara Sep 26 '17 at 10:38
  • Check Update 2 in the answer, there is the code on how to do just that. – Clive Ciappara Sep 26 '17 at 10:40
  • I appreciate your effort and thanks once again @Clive Ciappara. – AT-2017 Sep 26 '17 at 11:17
1

Even if you are adding status as key, there are 2 problems with your code.

  1. You need to create 2 objects to create 2 customers, one by one. You are adding customer only once, and assigning values twice.

  2. Console.ReadLine().ToUpper() - Remove the ToUpper() since you are adding values in mixed case. If you want to do that, initialize dictionary with StringComparer.InvariantCultureIgnoreCase.

This will work for you.

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 Kumar Singh
  • 4,393
  • 2
  • 9
  • 22
  • OK. Thanks for it @Amit. Suppose, what if I try to add those in a List<> or get list of objects from database table and assign them to the dictionary as value. Similar to this - **lst.Add(customer)** or retrieve data from database table. – AT-2017 Sep 26 '17 at 10:27
  • You can use LINQ in lists. `list.Where(t=>t.Status == status)` to search. In that case, you would need to use string.Contains with FindAll as shown here. https://stackoverflow.com/a/5116205/7974050 – Amit Kumar Singh Sep 26 '17 at 10:31
  • I appreciate your effort and thanks once again @Amit. – AT-2017 Sep 26 '17 at 11:19
1

First of all your dictionary key should be customerId not status. it will be a good practice to check if dictionary contains the key other wise it will throw the exception already same key is added. so its better to check then perform add or update in the 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";
   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
  • 1,182
  • 13
  • 38
1

Your are not getting any output because your are converting your input to uppercase while you have insert the keys in pascalcase and in case of C# collections keys are case sensitive. in this way your input does not matched to any key in collection

change your line number : 29 to this code

 string status = Console.ReadLine();

and insert "Inactive" from you console this key exist in your collection so you will desired result..

1

If you already has the list and want to create a Dictionary<string, List<Customer>> you can do it with this:

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

And iterate it:

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

But,

I don't see the value in doing so. if you need to get all the customers with a specific status stay with what you have - a simple linq query.

Ofir Winegarten
  • 9,215
  • 2
  • 21
  • 27
  • That's what I was looking for and you made it look so easy. Thanks @Ofir Winegarten. I've two questions. 1) The above that you have provided and with `Linq`, I guess, there would be performance issue. I mean with the above, it'll work more quicker than `Linq`. Correct me if I am wrong though it uses **foreach** loop. 2) I used others code as well. When there are duplicate values in the dictionary, it threw exception. But with the above, it worked perfectly for duplicates like right now there are two **Active** and **Inactive** status values. – AT-2017 Sep 26 '17 at 11:23
  • You're welcome. regarding your questions: 1. Unless the list is huge and you are executing the linq many times, there's no point in moving to dictionary. Don't forget that it still has to transform it to dictionary from list. so what's the point? The number 2 question seems more like a statement to me, isn't it? :-) – Ofir Winegarten Sep 26 '17 at 11:40
  • OK. Got it. Thanks for your time and effort. – AT-2017 Sep 26 '17 at 12:18