Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
This question was closed Mar 11, 2014 at 01:35 PM by raycosantana for the following reason:

The question is answered, right answer was accepted

avatar image
1
Question by raycosantana · Mar 11, 2014 at 12:34 PM · listscomparelinq

Compare two Lists and get the items that are not in both lists

Having two lists (LIST), how can I compare two Lists get the items that not in both lists , I know I probably need to use LINQ and I have been trying to learn about it but I'm not good enough with it yet.

I have two lists, one is for levels that are available for sale and other is the levels already bought by the player, I want to display at the shop only the levels that not bought by the player yet.

This is the part where I display the levels that are for sale:

 Scrollbar = GUILayout.BeginScrollView(Scrollbar);
         
         for (int n = 0; n < Levels.Count; n++){
         
             GUILayout.Box (Levels[n].newName);
             GUILayout.Box (Levels[n].newDescription);
             GUILayout.Box ("" + Levels[n].newPrice);
             
             if (GUILayout.Button("Buy")){
                     if (Status.Gold < Levels[n].newPrice){
                         Status.BoughtLevels.Add(new Level (Levels[n].newName,Levels[n].newDescription,Levels[n].newIndex,Levels[n].newPrice));
                         Status.Gold -= Levels[n].newPrice;
                         }
                         
                     
                     }
                 }

I have been trying to use if (Status.BoughtLevels.Contains(i=>i.Name != Levels[n].newName)){ Where Status.BoughtLevels are the levels bought by the player and while I don't get any error it simply doesn't display anything.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

  • Sort: 
avatar image
3
Best Answer

Answer by Bunny83 · Mar 11, 2014 at 01:06 PM

So you basically want to subtract the "bought level set" from the "available level set" as said in set theory.

either iterate through your available list and doing a Contains check each iteration or create a copy of the available list, iterate through the bought list and remove each item from the copied list.

BTW: it seems you create multiple Level objects for each level. This will always get you in trouble. Make sure you only create 1 instance for each level.

So when you bought a level you should do

 Status.BoughtLevels.Add(Levels[n])

If you have only one instance per level you can simply do:

 // first way
 for (int n = 0; n < Levels.Count; n++)
 {
     if (!Status.BoughtLevels.Contains(Levels[n]))
     {
         // display the level so it can be bought
     }
 }

Keep in mind that this is a O(n²) complexity. So if you have about 100 levels it has to do 10000 comparisons internally. If you do this in OnGUI you have to do this twice each frame which could get you in trouble. It's better to filter out which levels can be bought beforehand and just display this list

 // second way
 List<Level> GetBuyableLevels()
 {
     var tmp = new List<Level>(Levels); // get a copy of all levels
     foreach(var L in Status.BoughtLevels)
         tmp.Remove(L);
     return tmp;
 }

This has still a O(n²) compplexity (you can't really get around this when using two lists) but you only do it once when the BoughtLevels list changes

Another common and more easier way is to add a "bought" boolean to your level object. That way you don't need a seperate list and each level has it's bought state. This simplyfies all lookups to O(n). You can simply filter the list with linq like this:

 foreach(Level L in Levels.Where(i=>!i.bought))
 {
     // draw GUI
 }

This would display only those levels which aren't bought yet. To "buy" one you just set the levels bought field to true.

Without more information on how you save / get the bought levels / available levels i can't suggest anything more specific.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image raycosantana · Mar 11, 2014 at 01:33 PM 0
Share

Thanks, I think I will try the Boolean idea, it seems by far the easiest. I will close this now, Thanks!

avatar image
3

Answer by stevethorne · Mar 11, 2014 at 12:56 PM

Using LINQ here's what you can do. There may be better alternatives, but this is the best I can think of.

 List<string> list;
 List<string> list2;
 List<string> results = list.Except( list2 ).ToList().AddRange( list2.Except( list ) );

EDIT: I should also mention that this is the best I can think of in LINQ. There are probably better solutions outside of LINQ.

Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image whydoidoit · Mar 11, 2014 at 01:05 PM 2
Share

It could be more succinctly put as:

   var results = list.Except(list2).Concat(list2.Except(list)).ToList();
avatar image Bunny83 · Mar 11, 2014 at 01:10 PM 0
Share

I think he only wants the results from one list (the Level list). I don't think it's possible to have a level in the bought list but not in the Levels list. The title is a bit misleading i guess. I also thought he wants a "xor combine" but looking at the problem it seems he just wants the levels which aren't bought yet.

avatar image stevethorne · Mar 11, 2014 at 01:14 PM 0
Share

So then he wants this?

 results = BoughtLevels.Except( Levels ).ToList();
avatar image Bunny83 · Mar 11, 2014 at 01:20 PM 0
Share

No, the other way round. Levels contains all levels. Omitting all levels from a subset would give you an empty list ;)

     BuyableLevels = Levels.Except( BoughtLevels ).ToList();

However as i said in my answer it seems he creates multiple instances for the same level so all those linq functions won't work since you can't compare the instances directly.

avatar image stevethorne · Mar 11, 2014 at 01:22 PM 0
Share

Ah I see. Well then you should really view Bunny's answer here.

Follow this Question

Answers Answers and Comments

23 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How do I compare two lists for equality (not caring about order) C# 6 Answers

bool to true from a list comparison. 1 Answer

Comparing two lists to find the difference 1 Answer

Some Dictionary LINQ functions not cooperating? 1 Answer

Understanding Linq and orderbydescending 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges