Ok, I'm pretty sure isNumber is finally working. Thanks to everyone for the help. I think I'm almost ready to start working on this project for real. I'm just trying to wrap my head around lists.
What I'm doing is trying to check a bunch of inputs at once if they are numbers and store the results in a list. That way, to find out if one of them is a number, I can just check the corresponding value in the second list to find out.
So, my problem is that I'm clearly putting 3 things in my list, but when I have it print out the count of items it always displays 2. What the heck is wrong with this? Specifically, why does areNumbers always return a list of length 2 when I am obviously making it at least as long as numberOfNumbers?
PS I know my code doesn't look very nice yet. I want to get the basics right before I learn about style.
static void Main(string[] args)
{
var maybe = new ArrayList(3);
maybe.Add(100f);
maybe.Add("not a number");
maybe.Add(1000);
Console.WriteLine(areNumbers(maybe).Count);
Console.ReadLine();
}
static ArrayList areNumbers(ArrayList maybeNumbers)
{
var theResults = new ArrayList(0);
var numbersEnumerator = maybeNumbers.GetEnumerator();
var numberOfNumbers = 0;
try
{
for (; ; )
{
numberOfNumbers = numberOfNumbers + 1;
numbersEnumerator.MoveNext();
var myIsNumber = isNumber(numbersEnumerator.Current);
var myAreNumbers = new ArrayList(numberOfNumbers);
myAreNumbers.Add(theResults);
myAreNumbers.Add(myIsNumber);
theResults = myAreNumbers;
}
}
catch (InvalidOperationException)
{
return theResults;
}
}
static bool isNumber(object theObject)
{
var s = theObject.GetType().ToString().ToUpper();
Console.WriteLine(s);
return theObject is int || theObject is Int64 || theObject is float || theObject is double;
}
Like the commenters stated, the return value areNumbers will at most ever be an ArrayList with 2 items (first item would be an ArrayList of booleans for items 0 thru N-2; the second item would be a boolean value for the (N-1)th value). If I stepped through the code in my head correctly, you would get an empty ArrayList if you sent it an empty ArrayList.
After one item:
areNumbers[0]: [] // empty ArrayList
areNumbers[1]: true
After two items:
areNumbers[0]: [[], true] // after first item
areNumbers[1]: false
After three items
areNumbers[0]: [[[], true], false] // after second item
areNumbers[1]: true
If you were to call with a 4th value that was numeric:
areNumbers[0]: [[[[], true], false], true]
areNumbers[1]: true
Now hopefully you aren't stuck in the pre-generics & pre-LINQ world...
Where will filter based on your isNumber function:
var maybeNumbers = new List<object>{ 100f, "not a number", 1000 };
var areNumbers = maybeNumbers.Where(isNumber).ToList();
Assert.AreEqual(2, areNumbers.Count()); //passes!
If you're pre-LINQ, try this:
List<object> maybeNumbers = new List<object>();
maybeNumbers.Add(100f);
maybeNumbers.Add("not a number");
maybeNumbers.Add(1000);
List<object> areNumbers = new List<object>();
foreach(object maybe in maybeNumbers)
{
if (isNumber(maybe))
areNumbers.Add(maybe);
}
Pre-generics (may not compile...)
ArrayList maybeNumbers = new ArrayList();
maybeNumbers.Add(100f);
maybeNumbers.Add("not a number");
maybeNumbers.Add(1000);
ArrayList areNumbers = new ArrayList();
foreach(object maybe in maybeNumbers)
{
if (isNumber(maybe))
areNumbers.Add(maybe);
}
This will loop though a list of objects and give you a boolean response letting you know if they are numeric, which I think is what your code is doing in the end.
var testNumbers = new List<object>();
testNumbers.Add(15);
testNumbers.Add("AUUUGHH");
testNumbers.Add(42);
foreach (var i in testNumbers)
Console.WriteLine(Microsoft.VisualBasic.Information.IsNumeric(i));
Make sure you add a reference to the Microsoft.VisualBasic namespace in order to use IsNumeric()
1.don't rely on try/catch for normal code flow. try/catch is for catching exceptional situations
2.why do you need to build a isNumber method? double.tryParse or Convert.ToDouble() will do similar things (google up to find the difference)
3.No ideea what myAreNumbers is supposed to do but you are basically adding a bool and a list to a new list on every iteration
static ArrayList areNumbers(ArrayList maybeNumbers)
{
var theResults = new ArrayList(0);
foreach(var possibleNumber in maybeNumbers)
{
double myDouble;
if (double.tryParse(possibleNumber, out myDouble))
theResults.Add(possibleNumber);// OR theResults.Add(myDouble); //depending on what you want
}
return theResults;
}
get rid of endless loop
iterate through your maybe numbers
surround with try ... catch only isNumber
If have exception do not increase number of numbers.
And do not return generics for this because what you really need to return is an integer only.
You need sth like (pseudo code):
numberOfNumbers = 0;
while ( there is sth to handle )
{
take element to handle
try
{
check it
numberOfNumbers++;
}
catch ( )
{
// not a number
}
go to the next element
}
return numberOfNumbers
Assuming of course that isNumber throws some execption when your maybe number is not a number.
Try this:
static void Main(string[] args)
{
var maybe = new ArrayList(3);
maybe.Add(100f);
maybe.Add("not a number");
maybe.Add(1000);
foreach (var item in maybe)
{
Console.WriteLine(item);
}
ArrayList res = new ArrayList(maybe.ToArray().Where((o) => o.IsNumber()).ToArray());
foreach (var item in res)
{
Console.WriteLine(item);
}
}
public static bool IsNumber(this object item)
{
const TypeCode filter = TypeCode.Double | TypeCode.Int16 | TypeCode.Int32 | TypeCode.Int64
| TypeCode.Single | TypeCode.UInt16 | TypeCode.UInt32 | TypeCode.UInt64;
Type t = item.GetType();
if (t.IsPrimitive)
{
TypeCode code = System.Type.GetTypeCode(t);
return (code & filter) > 0;
}
return false;
}
Related
Sorry that I couldn't explain better in the question header. I'll try to define my question better here.
That's what I am doing - in my game, there is an option to use items on one another. For each pair of items, the game performs an action.
Currently, there are two variables that game uses for this: "ItemUsed" and "ItemUsedOn". First, the game chooses first item - its id goes to "ItemUsed", then he chooses second item, it's id goes to "ItemUsedOn". Then, there is a void that defines a specific action.
A short example of code:
if (ItemUsed == "itm_cable")
{
if (ItemUsedOn == "itm_towel")
SubMain.ItemsMergedText = "To achieve what?";
else if (ItemUsedOn == "itm_wet_towel")
SubMain.ItemsMergedText = "No, water will damage it";
else if (ItemUsedOn == "itm_glass")
SubMain.ItemsMergedText = "I don't need to cut the cable";
}
if (ItemUsed == "itm_book_electronics")
{
if (ItemUsedOn == "itm_towel")
SubMain.ItemsMergedText = "Why?";
if (ItemUsedOn == "itm_wet_towel")
SubMain.ItemsMergedText = "No, water will damage the book";
else if (ItemUsedOn == "itm_soap")
SubMain.ItemsMergedText = "Wrong plan";
else if (ItemUsedOn == "itm_hair")
SubMain.ItemsMergedText = "It won't help";
}
And there are many such pairs.
However, there is a problem with this approach. When two items are combined, their order doesn't matter, for example "itm_toolbox" can be "ItemUsed" and "itm_cable" can be "ItemUsedOn", but also can be the other way around, the result will be the same. How can this be achieved?
I did try using this in every "larger" if:
else
CombineItems(ItemUsedOn, "itm_book_edda");
But this doesn't always work, and I couldn't find why.
So, what I am looking for is function that gets 2 variables:
void CombineItems(string Item1, string Item2)
And then give same result in those cases:
if (Item1="Tomato")&&(Item2="Cucumber")
Item3="Salad"
if (Item1="Cucumber")&&(Item2="Tomato")
Item3="Salad"
My question: is there an easier way for this, without using so many "if's"?
Thank you in advance,
Evgenie
I'd recommend that you create yourself an eg UnorderedPair type, which overrides the behaviour of .Equals and/or ==, such that:
new UnorderedPair("Tomato", "Cumcumber") == new UnorderedPair("Cucumber", "Tomato");
Then you can reduce all of your if statements down to a simple dictionary:
combinedItems = new Dictionary<UnderedPair, string>
{
[new UnorderedPair("Tomato", "Cumcumber")] = "Salad",
[new UnorderedPair("Bread", "Filling")] = "Sandwich",
...
};
and your code for determining the text can then just be:
SubMain.ItemsMergedText = combinedItems[new UnorderedPair(ItemUsed, ItemUsedOn)];
You can use params(to treat them as array) and LINQ. Store the salad-items in an array too:
private string[] SaladItems = new string[] { "Tomato", "Cucumber" };
string CombineItems(params string[] Items)
{
bool isSalad = SaladItems.Length == Items.Length && !SaladItems.Except(Items).Any();
if (isSalad) return "Salad";
// other types ...
return null; // no match, exception?
}
Side-Note: if you want to accept "tomato"(so ignore the case) use:
!SaladItems.Except(Items, StringComparer.InvariantCultureIgnoreCase).Any()
You could make this endless list of comparisons a lot smaller if you structure the logic into separate parts.
First, I would create a list or so to keep the items and their result:
var items = new[] { new { Item1 = "tomato", Item2 = "Cucumber", Result = "Salad" }
, new { Item1 = "tomato2", Item2 = "Cucumber2", Result = "Salad2" }
};
Then find the matching item:
var match = items.FirstOrDefault
(itm => (itm.Item1 == Item1 && itm.Item2 == Item2)
|| (itm.Item1 == Item2 && itm.Item2 == Item1)
);
There are two approaches that can keep down the amount of duplication throughout the code:
Sort the items so they're alphabetical order:
if(Item1 > Item2) {
var tmp = Item2;
Item2 = Item1;
Item1 = tmp;
}
now all of your remaining code can assume that Item1 values will always be earlier alphabetically than Item2, so you'd only write:
if (Item1="Cucumber")&&(Item2="Tomato")
Item3="Salad"
Or, you can, after exhausting all of your options (again, written only once), call your method recursively with the parameters swapped:
void TakeAction(Item1, Item2) {
.
.
.
/* No matches */
else {
TakeAction(Item2,Item1);
}
}
var items= new HashSet<string>();
items.Add("tomato");
items.Add("Cucumber");
if(items.Contains("tomato") && items.Contains("Cucumber")) //Order does **NOT** matter
Item3="Salad";
foreach (Objecta a in aList())
{
foreach (Objectb b in bList)
{
if (a.variable != b.variable1 && a.variable() != b.variable2)
{
a.setVariable("Error");
}
}
}
The problem I am getting is that it goes through the foreach loop the first time and it sets variable to error without checking if other values (when it goes through the loop again) finds a match.
What I would like is to wait until it goes through all the lists and at the last foreach loop iteration if nothing in aList matches the variable target && variable source in bList then finally set it to Error flag.
Any suggestions to get around this will be appreciated.
Try doing it the other way around. Search for a match instead of searching for non-matches.
foreach (Objecta a in aList())
{
bool foundMatch = false;
foreach (Objectb b in bList)
{
if (a.variable == b.variable1 || a.variable() == b.variable2)
{
foundMatch = true;
break;
}
}
if (!foundMatch)
{
a.setVariable("Error");
}
}
I think this is what you are looking for. So if StoreList is the outer loop and LinkList is the inner loop. You want to search all the links to see if there's an ID that matches the store ID. If you find a match, stop searching the links. After the search through the links, set an error on the store if there was no match, then go to the next store.
foreach (Objecta a in aList())
{
var foundMatch = false;
foreach (Objectb b in bList)
{
if (a.variable == b.variable1 || a.variable() == b.variable2)
{
fondMatch = true;
break;
}
}
if (!foundMatch) a.setVariable("Error");
}
I think you want something like this:
First select all the item values from aList and bList and put them in a seperate array:
var aVals = aList.Select(x=>x.value1).ToArray();
var bListVals1 = bItems.Select(x=>x.value1).ToArray();
var bListVals2 = bItems.Select(x=>x.value2).ToArray();
var bVals = bListVals1.Concat(bListVals2);
Then, get the values both lists have in common:
var correctVals = bVals.Intersect(aVals);
These are the correct values and so all the other values are wrong:
var wrongVals = aVals.Except(correctVals);
Now you have the values that are wrong and can act accordingly:
wrongAItems = aList.Where(a => wrongVals.Contains(a.value));
foreach(wrongA in wrongAItems){
wrongA.setVariable("Error");
}
foreach (Store s in processFlowStores.getStoresList())
{
if (!processFlowLinks.Any(l => s.getNodeId() == l.getLinkSource() ||
s.getNodeId() == l.getLinkTarget()))
{
s.setID("Error: FailedOperation Error - 123.123.121");
}
}
EDIT: more compact solution using Linq. Basically, if none of the links has it as either source or target, mark it as error.
I need your advice on the following.
I have a multi-dimensional IList containing items which have an index, Id and Text. Normally I know the value of Id and based on that I need to get the Text. Both Id and Text values are read from a database.
What we are currently using to get the value of Text field is:
foreach (Object myObj in List)
{
if (((MessageType)myObj).Id == id)
{
return ((MessageType)myObj).Text;
}
}
When count in IList becomes large (more than 32K), it takes some time to process.
Question: Is there a way to efficiently get the Text value without iterating through the IList?
Things I tried without success:
Use List.IndexOf(Id) - did not work because IndexOf applies to text only.
Converting List to multi-dimensional array - failed on List.CopyTo(array,0) my guess because it is multi-dimensional:
string[] array=new string[List.Count,List.Count];
List.CopyTo(array,0);
I can not use a AJAX/JQuery solution because it is an existing(live) project and it will take too much to re-code.
Thanks
If you want fast searching by some identifier in a collection with 32k elements, you should use Dictionary<K,V> as your collection.
var dict = new Dictionary<IDType, MessageType>();
A Dictionary is basically a search tree where the elements are stored in a sorted way so an element with a specific key (in your case Id) can be found without looking at all elements. For more information see MSDN.
If you cannot refactor the collection to be a dictionary, you may initially fill the dictionary (slow) and then search in the dictionary (fast). This will only be faster if you do multiple searches before you fill the dictionary again, i.e. if your list does not change often.
foreach(object o in List)
{
var msg = (MessageType)o;
dict.Add(msg.Id, msg);
}
Searching then is easy:
MessageType msg = dict[id];
EDIT: Well, I was curious and wrote a test routine which compares the linear search and the dictionary approach. Here's what I used:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
namespace ConsoleApplication1
{
class MessageType
{
public string Id;
public string Text;
}
class Program
{
static void Main(string[] args)
{
var rand = new Random ();
// filling a list with random text messages
List<MessageType> list = new List<MessageType>();
for (int i = 0; i < 32000; i++)
{
string txt = rand.NextDouble().ToString();
var msg = new MessageType() {Id = i.ToString(), Text = txt };
list.Add(msg);
}
IList List = (IList)list;
// doing some random searches
foreach (int some in new int[] { 2, 10, 100, 1000 })
{
var watch1 = new Stopwatch();
var watch2 = new Stopwatch();
Dictionary<string, MessageType> dict = null;
for (int i = 0; i < some; i++)
{
string id = rand.Next(32000).ToString();
watch1.Start();
LinearLookup(List, id);
watch1.Stop();
watch2.Start();
// fill once
if (dict == null)
{
dict = new Dictionary<string, MessageType>();
foreach (object o in List)
{
var msg = (MessageType)o;
dict.Add(msg.Id, msg);
}
}
// lookup
DictionaryLookup(dict, id);
watch2.Stop();
}
Console.WriteLine(some + " x LinearLookup took "
+ watch1.Elapsed.TotalSeconds + "s");
Console.WriteLine("Dictionary fill and " + some
+ " x DictionaryLookup took "
+ watch2.Elapsed.TotalSeconds + "s");
}
}
static string LinearLookup(IList List, string id)
{
foreach (object myObj in List)
{
if (((MessageType)myObj).Id == id)
{
return ((MessageType)myObj).Text;
}
}
throw new Exception();
}
static string DictionaryLookup(Dictionary<string, MessageType> dict,
string id)
{
return dict[id].Text;
}
}
}
The results I got in Release / x86:
Number of | Time [ms] with | Time[ms] with | Speedup (approx.)
searches | linear search | dictionary(*) | with dictionary
----------+----------------+---------------+-----------------
2 | 1.161 | 2.006 | 0.6
----------+----------------+---------------+-----------------
10 | 2.834 | 2.060 | 1.4
----------+----------------+---------------+-----------------
100 | 25.39 | 1.973 | 13
----------+----------------+---------------+-----------------
1000 | 261.4 | 5.836 | 45
----------+----------------+---------------+-----------------
(*) including filling the dictionary once.
So, I was a bit optimistic to say that searching twice would already pay off. In my test application I have to search 10 times for the dictionary to be faster.
I'm sorry I could not make a more realistic example, my Ids are all sorted. Feel free to try modifying and experimenting though ;-)
From the looks of it you have a List<MessageType> here, which is not multi-dimensional. Rather the objects inside the list have multiple properties.
You could easily get them out with LINQ much faster than a loop most likely:
var text = (from MessageType msgType in myList
where msgType.Id == id
select msgType.Text).FirstOrDefault();
Or even easier with an inline LINQ statement:
var text = myList.Where(s => s.Id == id).Select(s => s.Text).FirstOrDefault();
NOTE: As mentioned in comments above, the speed of these LINQ statements are only as good as the object's position in the List. If it is the last object in the list, you will likely see the same performance discrepancy. Dictionary<Index, MessageType> is going to be much more performant.
Better way is to use ILookup.
For example:
var look = query.ToLookup(x => x.SomeID, y=> y.Name)
and use:
if (look.Contains(myID)){
var name = look[myID].First();
}
I am somewhat struggling with the terminology and complexity of my explanations here, feel free to edit it.
I have 1.000 - 20.000 objects. Each one can contain several name words (first, second, middle, last, title...) and normalized numbers(home, business...), email adresses or even physical adresses and spouse names.
I want to implement a search that enables users to freely combine word parts and number parts.When I search for "LL 676" I want to find all objects that contain any String with "LL" AND "676".
Currently I am iterating over every object and every objects property, split the searchString on " " and do a stringInstance.Contains(searchword).
This is too slow, so I am looking for a better solution.
What is the appropriate language agnostic data structure for this?
In my case I need it for C#.
Is the following data structure a good solution?
It's based on a HashMap/Dictionary.
At first I create a String that contains all name parts and phone numbers I want to look through, one example would be: "William Bill Henry Gates III 3. +436760000 billgatesstreet 12":
Then I split on " " and for every word x I create all possible substrings y that fullfill x.contains(y). I put every of those substrings inside the hashmap/dictionary.
On lookup/search I just need to call the search for every searchword and the join the results. Naturally, the lookup speed is blazingly fast (native Hashmap/Dictionary speed).
EDIT: Inserts are very fast as well (insignificant time) now that I use a smarter algorithm to get the substrings.
It's possible I've misunderstood your algorithm or requirement, but this seems like it could be a potential performance improvement:
foreach (string arg in searchWords)
{
if (String.IsNullOrEmpty(arg))
continue;
tempList = new List<T>();
if (dictionary.ContainsKey(arg))
foreach (T obj in dictionary[arg])
if (list.Contains(obj))
tempList.Add(obj);
list = new List<T>(tempList);
}
The idea is that you do the first search word separately before this, and only put all the subsequent words into the searchWords list.
That should allow you to remove your final foreach loop entirely. Results only stay in your list as long as they keep matching every searchWord, rather than initially having to pile everything that matches a single word in then filter them back out at the end.
In case anyone cares for my solution:
Disclaimer:
This is only a rough draft.
I have only done some synthetic testing and I have written a lot of it without testing it again.I have revised my code: Inserts are now ((n^2)/2)+(n/2) instead of 2^n-1 which is infinitely faster. Word length is now irrelevant.
namespace MegaHash
{
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
public class GenericConcurrentMegaHash<T>
{
// After doing a bulk add, call AwaitAll() to ensure all data was added!
private ConcurrentBag<Task> bag = new ConcurrentBag<Task>();
private ConcurrentDictionary<string, List<T>> dictionary = new ConcurrentDictionary<string, List<T>>();
// consider changing this to include for example '-'
public char[] splitChars;
public GenericConcurrentMegaHash()
: this(new char[] { ' ' })
{
}
public GenericConcurrentMegaHash(char[] splitChars)
{
this.splitChars = splitChars;
}
public void Add(string keyWords, T o)
{
keyWords = keyWords.ToUpper();
foreach (string keyWord in keyWords.Split(splitChars))
{
if (keyWord == null || keyWord.Length < 1)
return;
this.bag.Add(Task.Factory.StartNew(() => { AddInternal(keyWord, o); }));
}
}
public void AwaitAll()
{
lock (this.bag)
{
foreach (Task t in bag)
t.Wait();
this.bag = new ConcurrentBag<Task>();
}
}
private void AddInternal(string key, T y)
{
for (int i = 0; i < key.Length; i++)
{
for (int i2 = 0; i2 < i + 1; i2++)
{
string desire = key.Substring(i2, key.Length - i);
if (dictionary.ContainsKey(desire))
{
List<T> l = dictionary[desire];
lock (l)
{
try
{
if (!l.Contains(y))
l.Add(y);
}
catch (Exception ex)
{
ex.ToString();
}
}
}
else
{
List<T> l = new List<T>();
l.Add(y);
dictionary[desire] = l;
}
}
}
}
public IList<T> FulltextSearch(string searchString)
{
searchString = searchString.ToUpper();
List<T> list = new List<T>();
string[] searchWords = searchString.Split(splitChars);
foreach (string arg in searchWords)
{
if (arg == null || arg.Length < 1)
continue;
if (dictionary.ContainsKey(arg))
foreach (T obj in dictionary[arg])
if (!list.Contains(obj))
list.Add(obj);
}
List<T> returnList = new List<T>();
foreach (T o in list)
{
foreach (string arg in searchWords)
if (dictionary[arg] == null || !dictionary[arg].Contains(o))
goto BREAK;
returnList.Add(o);
BREAK:
continue;
}
return returnList;
}
}
}
I'm currently writing a simple app to compare two lists and return differences if any are found.
Note - [int] imaginary index for the purpose of this explanation
//---------------Prep----------------------------
ArrayList list1 = new ArrayList();
ArrayList storage = new ArrayList();
ArrayList list2 = new ArrayList();
string path = Application.ExecutablePath;
string root = Path.GetDirectoryName(path);
//---------------END Prep------------------------
//---------------Load content into list1------------------------
StreamReader objReader = new StreamReader(root + "/healthy.txt");
string sLine = "";
while (sLine != null)
{
sLine = objReader.ReadLine();
if (sLine != null)
list1.Add(sLine);
}
objReader.Close();
//---------------END Load content into list1------------------------
//---------------Load content into list2------------------------
string[] files = Directory.GetFiles(root, "*.txt", SearchOption.AllDirectories);
foreach (string file in files)
{
storage.Add(file.ToString());
}
foreach (string sOutput2 in storage)
{
list2.Add(GetMD5HashFromFile(sOutput2));
}
//---------------END Load content into list2------------------------
I tried everything, but it seems that I cannot crack this.. How do I ''loop'' through both lists and compare each item side by side in order then return the one's in list two that do not match the control list(list one)?
Logically the program would return ''More work'' as the wrong entry, because both "music" and "more work" are in the third row of their respective lists, they get checked and do not match. List 1 is control, so list 2's entry gets recorded as the odd one out.
Now I have tried it right and left, but I cannot make it happen.. Anyone out there who would be willing to shed some light on this or perhaps even guide me through to the right answer?
Many thanks
EDIT: Added my code for both arrayLists, im only missing the comparison function...
No particular reason for using ArrayList, any suggestions that would make this process easier are very welcome.
For starters, let's use a more modern way to read the lines:
IEnumerable<string> list1 = File.ReadLines("file1");
IEnumerable<string> list2 = Directory.EnumerateFiles("folder",
SearchOption.AllDirectories);
And then the list of files from list2 that are not in list1 :
IList<string> difference = list2.Except(list1).ToList();
ArrayList diffs = new ArrayList();
for(int i=0;i<N;i++) {
if(!one.Item(i).equals(two.Item(i)) )
diffs.Add(two.Item(i));
}
N = number of items coomon to both lists.
diffs = the arraylist with the odd ones of list two
If you want only the first odd entry from list two , then add a break into the loop. Here , the type of objects in the list is assumed to have defined an appropriate equals(Object obj)method.
Between these you can get the results you want.
IEnumerable<object> result = one.ToArray().Intersect(two.ToArray()); //Gives you what is the same
one.ToArray().Except(two.ToArray()); //Gives you wants in one not two
two.ToArray().Except(one.ToArray()); //Gives you wants in two and not in one
Here's a simple loop with integers that should work with any version the the framework.
If you have custom objects, here are guidelines for overriding Equals:
http://msdn.microsoft.com/en-us/library/ms173147(v=vs.80).aspx
ArrayList left = new ArrayList();
ArrayList right = new ArrayList();
left.Add(1);
left.Add(2);
left.Add(3);
right.Add(1);
right.Add(2);
right.Add(4);
bool areEqual = CompareArrayList(left, right);
private bool CompareArrayList(ArrayList left, ArrayList right)
{
if (left == null && right == null)
{
return true;
}
if (left == null || right == null)
{
return false;
}
if (left.Count != right.Count)
{
return false;
}
for (int i = 0; i < left.Count; i++)
{
if (!left[i].Equals(right[i]))
{
return false;
}
}
return true;
}