Oliver
Oliver

Reputation: 119

Trying to compare two lists c# - Should work?

I have a method that looks like this:

GetDrawing(Dictionary<string, List<string>> AllDrawings, Dictionary<string, bool> ImportData, string[] ItemsToCompare)

Firstly, the method creates a new List<string> with all the items from ImportData<string, bool> that have the value true and can be found in string[] ItemsToCompare

Secondly, I would like to compare the new List<string> with the List from AllDrawings<string, List<string>>. The method is in the end supposed to return a string with the key from AllDrawings<string>, List<String>> where the two lists match.

I have now spent a lot of hours trying to figure this out myself and also tried every answer I could find to similar questions here on Stackoverflow but with no luck.

Below is the full code for my method. As mentioned above I've tried a lot of different methods to compare the lists but the one following below is the latest try.

  public static string GetDrawing(Dictionary<string, List<string>> AllDrawings, Dictionary<string, bool> ImportData, string[] ItemsToCompare)
    {
        string FinalDrawing = "";
        try
        {
            List<string> AllCorrect = new List<string>();
            foreach (var item in ImportData)
            {
                if (item.Value == true && ItemsToCompare.Contains(item.Key))
                    AllCorrect.Add(item.Key);
            }

            AllCorrect.Sort();

            foreach (var DrawItem in AllDrawings)
            {

                DrawItem.Value.Sort();
                var match = AllCorrect.SequenceEqual(DrawItem.Value);

                if (match == true)
                {
                    FinalDrawing = DrawItem.Key;
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        return FinalDrawing;
    }

My problem is that the return value from var match = AllCorrect.SequenceEqual(DrawItem.Value); is false and therefore the FinalDrawing is never set.

All answers are very appreciated. Thanks in advance!

Upvotes: 2

Views: 126

Answers (3)

Gil Roitto
Gil Roitto

Reputation: 335

If the strings really match also for casing your code would be correct. I propose you inspect your string sequences - create an readable string and add appropriate break points. Also try to sort case-insensitive if that is what is missing here

    AllCorrect.Sort(StringComparer.InvariantCultureIgnoreCase);
    var AllCorrectInfo = string.Join(", ", AllCorrect.ToArray());
    foreach (var DrawItem in AllDrawings)
    {

        DrawItem.Value.Sort();
        var DrawItemInfo = string.Join(", ", DrawItem.Value.ToArray());

        var match = AllCorrect.SequenceEqual(DrawItem.Value, StringComparer.InvariantCultureIgnoreCase);

        if (match == true)
        {
            FinalDrawing = DrawItem.Key;
        }
    }

Upvotes: 0

quetzalcoatl
quetzalcoatl

Reputation: 33526

Ok.. I already said that in comments, but just to make sure that you don't get yelled at too much for not-using-linq and such:

your program seems correct up to the point you told us.

Here's a simple test. I provided some stub data that cover all things that you seem to check:

  • only true things from importedata
  • only things that are listed in itemstocompare
  • input lists are not sorted

-> http://rextester.com/HAE73942

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

public class Program
{
    // your original function, nothing changed
    public static string GetDrawing(Dictionary<string, List<string>> AllDrawings, Dictionary<string, bool> ImportData, string[] ItemsToCompare)
    {
        string FinalDrawing = "";
        try
        {
            List<string> AllCorrect = new List<string>();
            foreach (var item in ImportData)
            {
                if (item.Value == true && ItemsToCompare.Contains(item.Key))
                    AllCorrect.Add(item.Key);
            }

            AllCorrect.Sort();

            foreach (var DrawItem in AllDrawings)
            {

                DrawItem.Value.Sort();
                var match = AllCorrect.SequenceEqual(DrawItem.Value);

                if (match == true)
                {
                    FinalDrawing = DrawItem.Key;
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        return FinalDrawing;
    }

        public static void Main(string[] args)
        {
            var allDrawings = new Dictionary<string, List<string>>();
            allDrawings.Add("aaa", new List<string>{ "a03", "a01", "a02" }); // originally unsorted
            allDrawings.Add("bbb", new List<string>{ "b03", "b01", "b02" }); // originally unsorted
            allDrawings.Add("ccc", new List<string>{ "c03", "c01", "c02" }); // originally unsorted

            var import = new Dictionary<string, bool>();
            import.Add("b01", false); // falsey
            import.Add("a05", true); // not in comparison
            import.Add("a03", true);
            import.Add("c01", false); // falsey
            import.Add("a02", true);
            import.Add("a04", true); // not in comparison
            import.Add("a01", true);

            var toCompare = new string[9];
            toCompare[0]="a01"; toCompare[1]="a02"; toCompare[2]="a03";
            toCompare[3]="b01"; toCompare[4]="b02"; toCompare[5]="b03";
            toCompare[6]="c01"; toCompare[7]="c02"; toCompare[8]="c03";

            var result = GetDrawing(allDrawings, import, toCompare);

            Console.WriteLine("Result: " + result);
        }
}

it works fine and prints aaa as it should.

This means that you had to have overlooked something in the input data. Maybe some strings are uppercase/lowercase? Maybe some strings have whitespaces inside and others not?

Upvotes: 1

Fabjan
Fabjan

Reputation: 13676

This code :

        List<string> AllCorrect = new List<string>();

        foreach (var item in ImportData)
        {
            if (item.Value == true && ItemsToCompare.Contains(item.Key))
                AllCorrect.Add(item.Key);
        }

        AllCorrect.Sort();

Can be reduced to :

     List<string> AllCorect = ImportData.Where(vp => 
       ItemsToCompare.Contains(vp.Key) && vp.Value).Select(vp => vp.Key).OrderBy(vp => vp).ToList();

To solve the second problem you can do :

return AllDrawings.First(l => l.Value.OrderBy(l2 => l2).SequenceEqual(AllCorect)).Key;

P.S. If First() always throws an exception then it suggests that problem lays in how this lists are filled with values and this is a different question.

Example :

    public static string GetDrawing(Dictionary<string, List<string>> AllDrawings, Dictionary<string, bool> ImportData, string[] ItemsToCompare)
    {
        List<string> AllCorect = ImportData.Where(vp => 
           ItemsToCompare.Contains(vp.Key) && vp.Value).Select(vp => vp.Key).OrderBy(vp => vp).ToList();

        return AllDrawings.First(l => l.Value.OrderBy(l2 => l2).SequenceEqual(AllCorect)).Key;
    }


    static void Main(string[] args)
    {
        List<string> list1 = new List<string>() { "one", "two", "three" };
        List<string> list2 = new List<string>() { "five", "six", "seven" };

        Dictionary<string, List<string>> dict = new Dictionary<string, List<string>>()
        {
            {"first", list1}, {"second", list2}
        };

        string[] itemsToCompare = { "one", "two", "three" };

        var dict2 = new Dictionary<string, bool>()
        {
            {"one", true},
            {"two", true},
            {"three", true}
        };

        var result = GetDrawing(dict, dict2, itemsToCompare);

        Console.WriteLine(result);
    }

Output : first

Upvotes: 0

Related Questions