简体   繁体   中英

advanced list comparison in C#

I started comparing lists for my little project. So far I can compare if the same items exists, or one value of this item fits the same value of another lists item. Atm Im comparing the names from two lists. I changed some code I found for my purpose.

public class TestResources
{
     public string Name;
     public int Amount;

     public TestResources(string name, int amount)
     {
          Name = name;
          Amount = amount;
     }
}

TestResources[] ListResInStock = { new TestResources("wood", 1000), new TestResources("stone", 1000), new TestResources("sand", 1000), new TestResources("water", 1000) };
TestResources[] ListResNeeded = { new TestResources("wood", 800), new TestResources("stone", 800), new TestResources("sand", 375) };

private bool ContainsResourceName(IEnumerable<TestResources> ListResNeeded, IEnumerable<TestResources> ListResInStock)
{
     bool result;

     var list1WithName = ListResNeeded.Select(s => s.Name).ToList();
     var list2WithName = ListResInStock.Select(s => s.Name).ToList();

     result = !list1WithName.Except(list2WithName).Any();

     return result;
}

the function is called with:

Console.WriteLine("ListResInStock contains ListResNeeded:   ===> " + ContainsResourceName(ListResNeeded, ListResInStock) + " <===");    // True
Console.WriteLine("ListResNeeded contains ListResInStock:   ===> " + ContainsResourceName(ListResInStock, ListResNeeded) + " <===");    // False

Now I want to change it, so that it only returns true, if the name of the ressNeeded is there and the amount of ressInStock is >= the Amount of RessNeeded (for all resources of course).

Also If you could explain this part var list1WithName = ListResNeeded.Select(s => s.Name).ToList(); In detail to me would be nice because im not 100% sure what it does.

I really appreciate your help :-)

It's simply

private bool ContainsResourceName(IEnumerable<TestResources> ListResNeeded, IEnumerable<TestResources> ListResInStock)
{
     return ListResNeeded.All(resNeeded => 
         ListResInStock.Any(resInStock => 
              resInStock.Name == resNeeded.Name && 
              resInStock.Amount >= resNeeded.Amount
         )
     );
}

To understand the meaning of .Select , .All , .First and many other functions of so called IEnumerable interface, you'd have to learn about lazy evaluation in C#, and there's too much to say.

ListResNeeded.Select(s => s.Name).ToList(); and other operations with enumerators are easier to read from the end. So from the end: you make a list (of what?) of elements produced by Select function (what does it produce?) it takes a resource s and returns s.Name of it (where are these resources coming from?) from the list ListResNeeded.

Again, you have to read more about IEnumerator in C#, and about lazy evaluation in general. It's an inportant concept in programming.

PS And some warnings about the code you tried to use. What you do there:

var list1WithName = ListResNeeded.Select(s => s.Name).ToList();
var list2WithName = ListResInStock.Select(s => s.Name).ToList();

is making full copy of both arguments that were passed into the function (imagine these arrays would be much much bigger, what's the point of copying them?).

And there you make a new (third) list after traversing both of the previous completely, while what you actually look for is just a boolean answer.

result = !list1WithName.Except(list2WithName).Any();

You don't have to traverse both lists completely before you know that the answer is false. You just need to find a first resource that is missing and then stop the search (it's much much lighter)

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