简体   繁体   中英

Cast IEnumerable<Dictionary<string,object>> to a single merged Dictionary C#

First of all, I have a class that looks like this:

class Bag
    {
        public string Name { get; set; }
        public int Number { get; set; }
    }

Then I have the larger Dictionary that looks like this:

Dictionary<string, List<Bag>> allBags = ParseLinesIntoBags(lines);

Now I want to get a Dictionary of the same type as the upper one, but with the condition that the List<Bag> must contain a specific name (in my case "shiny gold"). For the further clarification if the allBags has the following:

 { "black", new List<Bag>() {new Bag("red", 1), new Bag("blue", 2) } },
 { "yellow", new List<Bag>() {new Bag("shiny gold", 1), new Bag("blue", 2) } },
 { "pink", new List<Bag>() { new Bag("blue", 2), new Bag("shiny gold", 3), new Bag("green", 4) } }

the other Dictionary therefore should have:

{ "yellow", new List<Bag>() {new Bag("shiny gold", 1), new Bag("blue", 2) } },
{ "pink", new List<Bag>() { new Bag("blue", 2), new Bag("shiny gold", 3), new Bag("green", 4) } }

. The task which I'm solving is from AdventOfCode2020 day 7 ( LINK ).

EDIT : ( since the original didn't follow the standards. I also deleted my failed tries because they were too far from the solution, and would only result in additional confusion .)

So currently I have the following code (Special thanks to @AliReza for coming with an almost full solution):

using System.Collections.Generic;
using System.Linq;
namespace Day7
{
    public class Bag
    {
        public string Name { get; set; }
        public int Number { get; set; }
        public Bag(string name, int number)
        {
            Name = name;
            Number = number;
        }
    }
    public class Program
    {
        public static void Main(string[] args)
        {
            Dictionary<string, List<Bag>> allBags = new Dictionary<string, List<Bag>>(){
                { "black", new List<Bag>() {new Bag("red", 1), new Bag("blue", 2) } },
                { "yellow", new List<Bag>() {new Bag("shiny gold", 1), new Bag("blue", 2) } },
                { "pink", new List<Bag>() { new Bag("blue", 2), new Bag("shiny gold", 3), new Bag("green", 4) } }};
            string condition = "shiny gold";
            var containerBagsV =from item in allBags
                                from bag in item.Value
                                where bag.Name == condition
                                select new Dictionary<string, List<Bag>>() { { item.Key, item.Value.ToList() } };
        }
    }
}

I wonder now is there any way to strongly type the Dictionary insted of leaving it to var? If I change var to Dictionary<string, List> immidietly

Dictionary<string, List<Bag>> containerBagsV = from item in allBags
                                from bag in item.Value
                                where bag.Name == condition
                                select new Dictionary<string, List<Bag>>() { { item.Key, item.Value.ToList() } };

I get the following compile error:

Severity Code Description Project File Line Suppression State Error CS0266 Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<Day7.Bag>>>' to 'System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<Day7.Bag>>'. An explicit conversion exists (are you missing a cast?)

If I try to cast it

Dictionary<string, List<Bag>> containerBagsV = (Dictionary<string, List<Bag>>)(from item in allBags
                                from bag in item.Value
                                where bag.Name == condition
                                select new Dictionary<string, List<Bag>>() { { item.Key, item.Value.ToList() } });

I get the following exception: System.InvalidCastException: 'Unable to cast object of type

'WhereSelectEnumerableIterator 2[<>f__AnonymousType0 2[System.Collections.Generic.KeyValuePair 2[System.String,System.Collections.Generic.List 1[Day7.Bag]],Day7.Bag],System.Collections.Generic.Dictionary 2[System.String,System.Collections.Generic.List 1[Day7.Bag]]]' to type 'System.Collections.Generic.Dictionary 2[System.String,System.Collections.Generic.List 1[Day7.Bag]]'.'

I think you should get the idea with this example

    var allBags = new Dictionary<string, List<Bag>>
    {
        { "black", new List<Bag>()  { new Bag("red", 1), new Bag("blue", 2) } },
        { "yellow", new List<Bag>() { new Bag("shiny gold", 1), new Bag("blue", 2) } },
        { "pink", new List<Bag>() { new Bag("blue", 2), new Bag("shiny gold", 3), new Bag("green", 4) } }
    };
    
    var containerBag = from item in allBags
                       from bag in item.Value
                       where bag.Name == "shiny gold"
                       select item;
 // this return yellow and pink records, you can select bag here also if you want

also if you want a dictionary output :

var containerBag = from item in allBags
                       from bag in item.Value
                       where bag.Name == "shiny gold"
                       select new Dictionary<string, List<Bag>>() { { item.Key, item.Value.ToList() } }; 

UPDATE merged version :

var containerBag = from item in allBags
                       from bag in item.Value
                       where bag.Name == "shiny gold"
                       select item;   

Dictionary<string, List<Bag>> mergedDictionary = new(containerBag);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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