Search code examples
c#listdictionaryforeach

If an element exist in a list, ignore other similar elements in c#


I have got a string list with generated programmatically like this:

var list = new List<string>
{
    "anonim",
    "anonim şirket",
    "anonim şirketler",
    "tapu",
    "tapu senedi",
    "tapu kütüğü",
    "yaptırım",
    "müeyyide",
    "işçi",
    "işçi alacakları",
    "işçi hakları",
    "işçi lehine yorum ilkesi",
    "işçilik sözleşmesi",
    "limited şirket",
    "sınırlı ayni hak",
    "telif hakkı",
    "unutulma hakkı",
    "yolsuz tescil",
    "zamanaşımı"
};

It contains many repeated similar elements. So I thinked that ignore these with the help of dictinary. If dictionary key exists in the list, I want to ignore elements separated by commas in the dictionary value. Here is the dictionary:

var dict = new Dictionary<string, string>
{
    {"anonim şirket", "anonim, anonim şirketler"}, 
    {"tapu senedi", "tapu, tapu kütüğü"}, 
    {"yaptırım", "müeyyide"}, 
    {"işçi hakları", "işçi, işçi alacakları, işçi lehine yorum ilkesi, işçilik sözleşmesi"}
};

So the final list I want to get is as follows:

var new_list = new List<string>()
{
    "anonim şirket",
    "tapu senedi",
    "yaptırım",
    "işçi hakları",
    "limited şirket",
    "sınırlı ayni hak",
    "telif hakkı",
    "unutulma hakkı",
    "yolsuz tescil",
    "zamanaşımı"
};

I don't know how to do this. I thought of writing a foreach loop like below. But I don't know what to write in foreach loop.

var newList = new List<string>();
foreach (var l in list)
{
    // WHAT MUST I DO IN HERE?
}

Solution

  • A simple way to do this (but not the most efficient) would be to:

    1. make a copy of the original list
    2. loop through the keys of the dictionary
    3. if a key exists in the new list, remove the items specified in the value from the new list.

    We can split the value on the comma character to create a mini-list to iterate over for removal of items (note that it would be easier if you used a Dictionary<string, List<string>> instead):

    // Make a copy of the original list
    var new_list = list.ToList();
    
    // Loop through the dictionary
    foreach (var item in dict)
    {
        // If our new list contains a key
        if (new_list.Contains(item.Key))
        {
            // Loop through the values associated with 
            // that key and remove them from the list
            foreach(var value in item.Value.Split(',').Select(i => i.Trim()))
            {
                new_list.Remove(value);
            }
        }
    }
    
    // Display results
    Console.WriteLine(string.Join("\n", new_list));
    

    enter image description here


    EDIT: A more efficient way would probably be to create a list of items to exclude first, by searching for the dictionary keys in the list as we did before, but collecting all the values in a separate list, and then we can use the Except method to remove the items (which has the added benefit [to some] of being done in one line):

    var new_list = list.Except(dict
        .Where(item => list.Contains(item.Key))
        .SelectMany(item => item.Value.Split(',').Select(i => i.Trim())))
        .ToList(); // Call ToList() if you need a List and not just an IEnumerable