New to Lambda and LINQ expressions but I have this so far:
// Sample setup/data (all of it)
int[] placeIds = {1, 2, 3, 4, 5};
string[] animals = { "Cow", "Camel", "Elephant", "Goat", "Dog" };
var placeIdsList = new List<int>(placeIds);
var animalsList = new List<string>(animals);
So in the above setup, animals are unique and belong to places which have unqiue ids. I have a list of place ids and animals being input and I want to find the ids of the places an animal belongs to. Each place can only have one animal (so one to one relationship for this exercise).
int[] placeIdsInput = {1, 3, 5};
string[] animalsInput = { "Elephant", "Dog" };
var placeIdsInputList = new List<int>(placeIdsInput);
var animalsInputList = new List<string>(animalsInput);
In theory this weill return the placeIds of the elephant and the dog which let's say is 3 and 5. PlaceId's being input will alqays have a count >= count of animals input.
I am trying this but need help on the finishing step (I think):
var placeIdsOfAnimals = _getService.QueryWithNoTracking<Places>()
.Include(i => i.Animals)
.Where(q => q.Contains(placeIdsInputList))
.Select(q => new AnimalDTO
{
Id = q.Id,
Anaiml = q.Animal
})
.ToList();
No how do I pass in the animals I want to look for to get the place Ids of them returned?
CodePudding user response:
Inside your Where-Function you can modify the lambda so that it filters for only the animals that are inlcuded in your animalsInputList and only the placeIds that are included in your placeIdInputList. It would look like that:
var placeIdsOfAnimals = _getService.QueryWithNoTracking<Places>()
.Include(i => i.Animals)
.Where(q => q.Contains(placeIdsInputList)
&& animalsInputList.Contains(q.Animal)
&& placeIdsInputList.Contains(q.Id))
.Select(q => new AnimalDTO
{
Id = q.Id,
Anaiml = q.Animal
})
.ToList();
(The last part could already be covered by your q.Contains(placeIdInputList
) - but I am not sure how your Places and Animals data structure looks like internally, so I included it in my query)
If you now want it to only return the list of place Ids, you could exchange your current Select with the following:
.Select(q => q.Id)
CodePudding user response:
Well, I would create a dictionary to keep the values of animals and its place holder ids at first:
var dataSource = animals
.Zip(placeIds, (animal, placeId) => new { Key = animal, Value = placeId})
.ToDictionary(x => x.Key, x => x.Value);
Then, would use LINQ to fetch the animal Ids:
var output = animalsInput.Select(x => new
{
Id = dataSource.TryGetValue(x, out var placeId) ? placeId : -1,
Animal = x
});