1

I have a Dictionary and another List. What I am trying to achieve is a LINQ query to get all items out of the dictionary where any values from said dictionary are not in the List<string>. I found this post to be helpful, Linq Query Dictionary where value in List. And was able to write the following LINQ expression.

What I have so far: Data is the dictionary and PersonList is the list of strings.

var Persons = Data.Where(kvp => !PersonList.Contains(kvp.Key))
                  .ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

However, my results never actually return anything.

Update:

Dictionary<string, string> Data = new Dictionary<string, string>
{
    { "John", "aaa" },
    { "Tom", "bbb" },
    { "David", "ccc" }
};

List<string> PersonList = new List<string>
{
    "Tom",
    "Peter"
};

var Persons = Data.Where(kvp => !PersonList.Contains(kvp.Key))
                  .ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
Stefan
  • 652
  • 5
  • 19
Roman Cerny
  • 87
  • 2
  • 14
  • 3
    It would be awesome if you could share a [mcve] (including sample data **and clear expected results**). – mjwills Oct 23 '19 at 10:59
  • You want a left outer join. See msdn examples : https://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b – jdweng Oct 23 '19 at 11:59

4 Answers4

4

Is it possible that you made a typo here and meant to write this instead?

// changed to kvp.Value from kvp.Key
var Persons = Data.Where(kvp => !PersonList.Contains(kvp.Value))
                  .ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

This searches the values from the dictionary in the list and retains those entries which are not in the list, as per your question.

Tanveer Badar
  • 5,438
  • 2
  • 27
  • 32
2

Answering this myself as I've been looking into the problem from wrong angle. Following works as expected:

Dictionary<string, string> Data = new Dictionary<string, string>
{
    { "John", "aaa" },
    { "Tom", "bbb" },
    { "David", "ccc" }
};

List<string> PersonList = new List<string>
{
    "Tom",
    "Peter"
};

List<string> PersonListNotInDictionary = PersonList.Where(pl => !Data.ContainsKey(pl))
                                                   .ToList();
Roman Cerny
  • 87
  • 2
  • 14
  • 1
    `What I am trying to achieve is a linq query to get all items out of the dictionary where any values from said dictionary are not in the List.` That is the **opposite** of your answer. Your answer here is those from the list that aren't in the dictionary. – mjwills Oct 23 '19 at 11:45
  • Also note that if you want to filter the `List` you have, `RemoveAll()` is a much more performant option than using LINQ. – Tanveer Badar Oct 23 '19 at 11:56
1

It is possible that the contains doesn't work, because the items in the PersonList are other objects than the keys in your dictionary. The objects might be the same (have the same content), but if it are different object (different refences), than the contains will return false.

An example:

myObject = new myObject() { Id = 1 };

List<myObject> listOfObjects = new List<myObject>();
listOfObjects.Add(new myObject() { Id = 1 });

var result = listOfObjects.Contains(myObject); // returns false, because the item in the list is a different object than myObject

result = listOfObjects.Any(obj => obj.Id == myObject.Id); // returns true

I don't know what the PersonList consist of, but if the elements have, for instance, an Id property than you could do something like this:

var Persons = Data.Where(kvp => !PersonList.Any(person => person.Id == kvp.Key.Id))
              .ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
Stefan
  • 652
  • 5
  • 19
1

You can try following code snippet

var result = data.Where(d => PersonList.All(p => p != d.Value));