I'm doing a SAT Solver (mainly the DPLL or Partial DPLL) and I have the method for Unit Propogation. Basically what it does is that it checks whether there are any standalone literals, and removes that literal, and any instance found in the other clauses. Any Example would be
(x) (x,y) (w,z)
the Unit Propogation would be 'x' and when performing the unit prop it would leave only (w,z)
In this method I have several nested foreach loops and List<literals> <literals> is a custom made class which has 2 variables hasNegation (bool) and char literalCharacter
The Coding is below, and will explain from below
foreach (clauses c1 in listOfClauses)
{
if (c1.listOfLiterals.Count == 1)
{
literals l1 = c1.listOfLiterals[0];
solved.Add(l1);
foreach (clauses c2 in listOfClauses)
{
List<literals> tempList = new List<literals>();
foreach (literals l2 in listOfLiterals)
{
if (l2.solveDPLL(l1))
{
removable.Add(c2);
}
else
{
if (c2.listOfLiterals.Count == 1)
{
UNSAT = true;
return false;
}
else
{
if (l1.solveDPLL(l2))
{
tempList.Add(l2);
}
}
}
c2.listOfLiterals.RemoveAll(tempList); //obviously giving error
}
}
}
}
return true;
}
I have 2 List <literals> which are templist and listOfLiterals where the LATTER is the "parent"
I am tryign to remove the entries of listOfLiterals that match with tempList and I use c2.listOfLiterals.RemoveAll(tempList); obviously will output an error as it is not a Delegate.
I've searched a lot,even on stackoverflow, but every one of them compares either to an ID or an integer. In my case, since I'm just comparing 2 Lists, how can I do the delegate so that, the entries that are the same in both listOfLiterals and tempList are removed from listOfLiterals?
Many thanks
EDIT:
Literals Class
public class literals
{
public char literalCharacter { get; set; }
public bool negation { get; set; }
public literals(char lc, bool neg )
{
literalCharacter = lc;
negation = neg;
}
public bool solveDPLL (literals lit)
{
return ((Object.Equals(literalCharacter, lit.literalCharacter) && (negation == lit.negation)));
}
public String toString()
{
return literalCharacter + " : " + !negation;
}
}
If you're okay with using a little LINQ magic:
c2.listOfLiterals = c2.listOfLiterals.Except(tempList).ToList();
Or loop over the tempList:
foreach (var item in tempList)
{
c2.listOfLiterals.Remove(item);
}
You may need your literals class to implement IEqualityComparer<literal> and then provide an implementation for Equals and GetHashCode. See the MSDN page for Except for a good example of this.
Related
i have class strucur something like this
List<MainCat> AllCat;
public class MainCat
{
public string id { get; set; }
public string name { get; set; }
public List<subcat> subcat { get; set; }
}
public class subcat
{
public string id { get; set; }
public string name { get; set; }
public List<subsubcat> subsubcat { get; set; }
}
public class subsubcat
{
public string id { get; set; }
public string name { get; set; }
}
i want to get name by id,
for example i know the id is 69
i want get output like this
MainCat.name > subcat.name > subsubcat.name (if 69 found in subsubcat)
MainCat.name > subcat.name (if 69 found in subcat)
MainCat.name (if 69 found in MainCat)
If I've understood your requirement properly, this is a case where the query syntax can work wonders:
IEnumerable<string> MyFunc(IEnumerable<MainCat> mainCategories, string idToMatch)
{
return (from main in mainCategories
where main.id == idToMatch
select main.name)
.Concat(from main in mainCategories
from sub in main.subcat
where sub.id == idToMatch
select string.Format("{0} > {1}", main.name, sub.name))
.Concat(from main in mainCategories
from sub in main.subcat
from subsub in sub.subsubcat
where subsub.id == idToMatch
select string.Format("{0} > {1} > {2}", main.name, sub.name, subsub.name));
}
If you're only interested in the first match, this can be called like
string resultName = MyFunc(AllCat, "69").FirstOrDefault();
Because the query uses deferred execution, this will avoid calling the more complex queries if a match is found in the main category.
It is also possible to use the SelectMany function with the function call syntax, however, it gets much harder to follow e.g. the following is how I re-wrote the contents of the second .Concat(...) call in order to illustrate:
mainCategories.SelectMany(main => main.subcat, (main, sub) => new { Main = main, Sub = sub })
.SelectMany(pair => pair.Sub.subsubcat, (pair, subsub) => new { Main = pair.Main, Sub = pair.Sub, SubSub = subsub})
.Where(triplet => triplet.SubSub.id == idToMatch)
.Select(triplet => string.Format("{0} > {1} > {2}", triplet.Main, triplet.Sub, triplet.SubSub));
As I understand it, the query syntax compiles to something very similar to this behind the scenes.
Update after answer accepted, and I came back to look at my code again:
Another possibility would be to add an interface to all 3 classes (or unify them into a single class or derive from a common base class depending on real use case).
This allows a recursive implementation that can search to arbitrary depth (below are 2 different Linq-based implementations depending on whether you have a preference for one or other syntax):
public interface ITreeCat
{
string id { get; }
string name { get; }
IEnumerable<ITreeCat> subcat { get; }
}
// add explicit interface implemetantion to existing 3 classes
// e.g.
// IEnumerable<ITreeCat> ITreeCat.subcat { get { return subsubcat; } }
// IEnumerable<ITreeCat> ITreeCat.subcat { get { return Enumerable.Empty<ITreeCat>(); } }
IEnumerable<string> MyFunc(IEnumerable<ITreeCat> categories, string idToMatch, string prefix = "")
{
return (from cat in categories
where cat.id == idToMatch
select prefix + cat.name)
.Concat(from cat in categories
from recursiveResult in MyFunc(cat.subcat, idToMatch, prefix + cat.name + " > ")
select recursiveResult);
}
IEnumerable<string> MyFunc2(IEnumerable<ITreeCat> categories, string idToMatch, string prefix = "")
{
return categories.Where(cat => cat.id == idToMatch)
.Select(cat => prefix + cat.name)
.Concat(categories.SelectMany(cat => MyFunc2(cat.subcat, idToMatch, prefix + cat.name + " > ")));
}
This has the advantage that it continues to work if you later add a subsubsubcat etc.
All of the above code examples use a breadth-first search, and repeatedly enumerate the "parent" categories each time they go one level deeper.
In some applications a depth-first search may be a better choice, as each list is only enumerated once, in which case it's much easier to use foreach rather than Linq. Again, a recursive version is more concise than 3 nested loops with different classes:
IEnumerable<string> MyFuncDepthFirst(IEnumerable<ITreeCat> categories, string idToMatch)
{
foreach(var cat in categories)
{
if (cat.id == idToMatch)
yield return cat.name;
foreach (var subResult in MyFuncDepthFirst(cat.subcat, idToMatch))
yield return string.Format("{0} > {1}", cat.name, subResult);
}
}
This still assumes that multiple matches can occur. If we're just after the first match, then there's no need to use an iterator block at all, and the above function can be modified to return a simple string:
string FirstMatchingIdDepthFirst(IEnumerable<ITreeCat> categories, string idToMatch)
{
foreach(var cat in categories)
{
if (cat.id == idToMatch)
return cat.name;
string subResult = FirstMatchingIdDepthFirst(cat.subcat, idToMatch);
if(subResult != null)
return string.Format("{0} > {1}", cat.name, subResult);
}
return null;
}
var list = this.AllCat.Where(t=>t.subcat.Any(s=> subsubcat.contains(s));
You can go for a method like below
public static Type Find(string id, MainCat m)
{
if (m.id.Equals(id))
{
return m.GetType();
}
if (m.subcat.Any(a => a.id.Equals(id)))
{
return typeof(subcat);
}
if (m.subcat.Any(a => a.subsubcat.Any(b => b.id.Equals(id))))
{
return typeof(subsubcat);
}
return null;
}
and perform the search. Find the gist, https://gist.github.com/IshamMohamed/33d75064789d77d88404b8ffc9a17e94
In this way you can increase the number of inner lists (eg: subsubsubcat)
Per the code below, I have a GetOrderPreviewSecurity() method that returns a Security, which is a parent class to Stock and MutualFund.
The GetOrderPreviewSecurity() method only actually returns a Stock type or MutualFund type to a Security property. The issue I'm having is trying to access the Child-specific properties as described in the //comments below.
Is there a way I can force the cast or clean this up that is cleaner than "var newThing = (ChildClass)SecurityClass;" and using newThing?
public class Stock : Security
{
public string Ask;
public string Bid;
}
public class MutualFund : Security
{
public string AssetClass;
public string Category;
}
public Security PreviewSecurity;
public Security GetOrderPreviewSecurity(_orderTickerText){
//Do stuff
if (boolean thing)
return new Stock();
else if (boolean thing)
return new MutualFund();
else
return new Security("empty");
}
//Some stuff
private void ExecutePreviewOrder()
{
if (!string.IsNullOrEmpty(_orderTickerText) && _orderShareQuantity > 0)
{
//Returns a **Security**
PreviewSecurity = _portfolioService.GetOrderPreviewSecurity(_orderTickerText);
if (PreviewSecurity is Stock)
{
//PreviewSecurity is still a Security type.
//No Bid or Ask properties available
PreviewBid = PreviewSecurity.Bid;
PreviewAsk = PreviewSecurity.Ask;
}
else if (PreviewSecurity is MutualFund)
{
//PreviewSecurity is still a Security type.
//No AssetClass or Category propeties available
PreviewAssetClass = PreviewSecurity.AssetClass;
PreviewCategory = PreviewSecurity.Category;
}
}
}
You need to have a set of parentheses around the entire thing, like this:
if (PreviewSecurity is Stock)
{
PreviewBid = ((Stock)PreviewSecurity).Bid;
PreviewAsk = ((Stock)PreviewSecurity).Ask;
}
else if (PreviewSecurity is MutualFund)
{
PreviewAssetClass = ((MutualFund)PreviewSecurity).AssetClass;
PreviewCategory = ((MutualFund)PreviewSecurity).Category;
}
I think the issue is that the dot has higher precedence than the cast operator, so first the dot operator is applied, and then the cast operator is applied to whatever is returned by the dot operator.
I do not see any problem with casting the Security back once you have type checked it.
if (PreviewSecurity is Stock)
{
PreviewBid = (Stock)PreviewSecurity.Bid;
PreviewAsk = (Stock)PreviewSecurity.Ask;
}
else if (PreviewSecurity is MutualFund)
{
PreviewAssetClass = (MutualFund)PreviewSecurity.AssetClass;
PreviewCategory = (MutualFund)PreviewSecurity.Category;
}
Say I have a view model defined this way
public class DataVM
{
public int number { get; set; }
public string name { get; set; }
}
Then somewhere in my code I want to do this to populate DataListbox:
List<DataVM> data = new List<DataVM>();
for (int i = 0; i < data.Count; i++)
{
if (DataListbox.Items.Contains(data[i]))
{
//do nothing
}
else
{
DataListbox.Add(data[i]);
}
}
However, this line if (DataListbox.Items.Contains(data[i])) always evaluate to false even when that item is already in DataListbox and it should evaluate to true. I don't get why it doesn't work.
What am I doing wrong here and how do I fix it?
The reason why your code always evaluates false is because the .NET framework compares the pointers to the memory and not the variables content by default when using checking for equality of two objects.
So instead of using the built in Contains function you should iterate through all elements of the listbox and check by comparing an unique property if the item was already added to the listbox:
You would have to do something like this (using LINQ; Replace data[i].name and item.Value with the unique property):
bool listContainsItem = DataListbox.Items.Any(item => item.Value == data[i].name);
Or by using "old" coding style:
for (int i = 0; i < data.Count; i++)
{
bool itemAlreadyAdded = false;
foreach (var item in DataListbox.Items)
{
if (item.Value == data[i].name)
{
itemAlreadyAdded = true;
break;
}
}
if (itemAlreadyAdded)
{
//do nothing
}
else
{
DataListbox.Add(data[i]);
}
}
The Contains method uses the Equals method of the class being checked.
In this case the DataVM class needs to override the Equals method
public class DataVM
{
public int number { get; set; }
public stringname { get; set; }
public override bool Equals(object obj)
{
bool areEqual ;
areEqual = false ;
if((obj != null) && (obj instanceOf DataVM))
{
//compare fields to determine if they are equal
areEqual = (DataVM(obj)).number == this.number ;
}
return areEqual ;
}
public override int GetHashCode()
{
//calculate a hash code base on desired properties
return number ;
}
}
When you override the Equals method is necessary for you to override also the GetHashCode method
You cannt match your own classes. Even if the Properties are the same, it´s baisicaly not the same Object (In your case its not the same DataVM). It´s like trying to match your Blue car with an ather one, baisicaly it´s the same but the location for examle is different.
Try matching properties of the object or write an own function. (I made a function)
List<DataVM> data = new List<DataVM>();
for (int i = 0; i < data.Count; i++)
{
if (ListContainsDataVM(DataListbox.Items, data[i]))
{
//do nothing
}
else
{
DataListbox.Add(data[i]);
}
}
public bool ListContainsDataVM(List<DataVM> DataVMList, DataVM myDataVM)
{
foreach (var dataVm in DataVMList)
{
if (dataVm.number == myDataVM.number && dataVm.stringname == DataVM.stringname)
{
return true;
}
}
return false;
}
I cannot reply to previous answer, but this is the version as it should be I believe
bool listContainsItem = DataListbox.Items.Cast<DataVM>().Any(item => item.Value == data[i].name);
it was missing the cast...
On my case, I just want to check if my selected item on ComboBox exists in ListBox
This code works for me:
string selected_i = comboBox.SelectedItem; //selected_i = "selected item"
if(!listbox.Items.Contains(selected_i))
{
listbox.Items.Add(selected_i);
}
else{
MessageBox.Show("Item already exists in Listbox!");
}
public struct RegistryApp
{
public string VendorName;
public string Name;
public string Version;
}
I Have two List<RegistryApp> which hold all Applications currently installed on the Windows box. Why two? Well I have one List to hold all x86 Applications and one to hold all x64 Applications.
List<RegistryApp> x64Apps64List = new List<RegistryApp>();
List<RegistryApp> x64Apps32List = new List<RegistryApp>();
Once those two are populated with their appropriate data which was retrieved from the registry, I try the following to make sure there are no duplicates. This worked decently on List<string> but not working with List<RegistryApp>.
List<RegistryApp> ListOfAllAppsInstalled = new List<RegistryApp>();
IEnumerable<RegistryApp> x86Apps = x64Apps32List.Except(x64Apps64List);
IEnumerable<RegistryApp> x64Apps = x64Apps64List.Except(x64Apps32List);
foreach (RegistryApp regitem in x86Apps)
{
if ((regitem.Name != null) &&
(regitem.Name.Length > 2) &&
(regitem.Name != ""))
{
ListOfAllAppsInstalled.Add(regitem);
}
}
foreach (RegistryApp regitem in x64Apps)
{
if ((regitem.Name != null) &&
(regitem.Name.Length > 2) &&
(regitem.Name != ""))
{
ListOfAllAppsInstalled.Add(regitem);
}
}
Any way to pull this off?
EDITED
To remove items from a List of Structs that exist in another List you can see the solution provided by Cuong Le Here :
https://stackoverflow.com/a/12784937/1507182
By using the Distinct parameterless extension method on the List type, we can remove those duplicate elements.
Then, we can optionally invoke the ToList extension to get an actual List with the duplicates removed.
static void Main()
{
// List with duplicate elements.
List<int> mylist = new List<int>();
mylist.Add(1);
mylist.Add(2);
mylist.Add(3);
mylist.Add(3);
mylist.Add(4);
mylist.Add(4);
mylist.Add(4);
foreach (int value in mylist)
{
Console.WriteLine("Before: {0}", value);
}
// Get distinct elements and convert into a list again.
List<int> distinct = mylist.Distinct().ToList();
foreach (int value in distinct)
{
Console.WriteLine("After: {0}", value);
}
}
If my answer has solved your problem click Accept as solution button, doing it will help others know the solution.
For Execpt to work the thing you are using it on must be compareable. To make it work for your custom struct you will need to do one of two things, either override GetHashCode and Equals to be able to use Execpt with your struct:
public struct RegistryApp
{
public string VendorName;
public string Name;
public string Version;
public override bool Equals(object obj)
{
if (!(obj is MyStruct))
return false;
RegistryApp ra = (RegistryApp) obj;
return ra.VendorName == this.VendorName &&
ra.Name == this.Name &&
ra.Version == this.Version;
}
public override int GetHashCode()
{
return VendorName.GetHashCode() ^ Name.GetHashCode() ^ Version.GetHashCode();
}
}
or use the overload of Execpt that allows you to pass in your own comparer and pass that in. See the MSDN for an example
Question:
Can anyone tell me why my unit test is failing with this error message?
CollectionAssert.AreEquivalent failed. The expected collection contains 1
occurrence(s) of . The actual
collection contains 0 occurrence(s).
Goal:
I'd like to check if two lists are identical. They are identical if both contain the same elements with the same property values. The order is irrelevant.
Code example:
This is the code which produces the error. list1 and list2 are identical, i.e. a copy-paste of each other.
[TestMethod]
public void TestListOfT()
{
var list1 = new List<MyPerson>()
{
new MyPerson()
{
Name = "A",
Age = 20
},
new MyPerson()
{
Name = "B",
Age = 30
}
};
var list2 = new List<MyPerson>()
{
new MyPerson()
{
Name = "A",
Age = 20
},
new MyPerson()
{
Name = "B",
Age = 30
}
};
CollectionAssert.AreEquivalent(list1.ToList(), list2.ToList());
}
public class MyPerson
{
public string Name { get; set; }
public int Age { get; set; }
}
I've also tried this line (source)
CollectionAssert.AreEquivalent(list1.ToList(), list2.ToList());
and this line (source)
CollectionAssert.AreEquivalent(list1.ToArray(), list2.ToArray());
P.S.
Related Stack Overflow questions:
I've seen both these questions, but the answers didn't help.
CollectionAssert use with generics?
Unit-testing IList with CollectionAssert
You are absolutely right. Unless you provide something like an IEqualityComparer<MyPerson> or implement MyPerson.Equals(), the two MyPerson objects will be compared with object.Equals, just like any other object. Since the objects are different, the Assert will fail.
It works if I add an IEqualityComparer<T> as described on MSDN and if I use Enumerable.SequenceEqual. Note however, that now the order of the elements is relevant.
In the unit test
//CollectionAssert.AreEquivalent(list1, list2); // Does not work
Assert.IsTrue(list1.SequenceEqual(list2, new MyPersonEqualityComparer())); // Works
IEqualityComparer
public class MyPersonEqualityComparer : IEqualityComparer<MyPerson>
{
public bool Equals(MyPerson x, MyPerson y)
{
if (object.ReferenceEquals(x, y)) return true;
if (object.ReferenceEquals(x, null) || object.ReferenceEquals(y, null)) return false;
return x.Name == y.Name && x.Age == y.Age;
}
public int GetHashCode(MyPerson obj)
{
if (object.ReferenceEquals(obj, null)) return 0;
int hashCodeName = obj.Name == null ? 0 : obj.Name.GetHashCode();
int hasCodeAge = obj.Age.GetHashCode();
return hashCodeName ^ hasCodeAge;
}
}
I was getting this same error when testing a collection persisted by nHibernate. I was able to get this to work by overriding both the Equals and GetHashCode methods. If I didn't override both I still got the same error you mentioned:
CollectionAssert.AreEquivalent failed. The expected collection contains 1 occurrence(s) of .
The actual collection contains 0 occurrence(s).
I had the following object:
public class EVProjectLedger
{
public virtual long Id { get; protected set; }
public virtual string ProjId { get; set; }
public virtual string Ledger { get; set; }
public virtual AccountRule AccountRule { get; set; }
public virtual int AccountLength { get; set; }
public virtual string AccountSubstrMethod { get; set; }
private Iesi.Collections.Generic.ISet<Contract> myContracts = new HashedSet<Contract>();
public virtual Iesi.Collections.Generic.ISet<Contract> Contracts
{
get { return myContracts; }
set { myContracts = value; }
}
public override bool Equals(object obj)
{
EVProjectLedger evProjectLedger = (EVProjectLedger)obj;
return ProjId == evProjectLedger.ProjId && Ledger == evProjectLedger.Ledger;
}
public override int GetHashCode()
{
return new { ProjId, Ledger }.GetHashCode();
}
}
Which I tested using the following:
using (ITransaction tx = session.BeginTransaction())
{
var evProject = session.Get<EVProject>("C0G");
CollectionAssert.AreEquivalent(TestData._evProjectLedgers.ToList(), evProject.EVProjectLedgers.ToList());
tx.Commit();
}
I'm using nHibernate which encourages overriding these methods anyways. The one drawback I can see is that my Equals method is based on the business key of the object and therefore tests equality using the business key and no other fields. You could override Equals however you want but beware of equality pollution mentioned in this post:
CollectionAssert.AreEquivalent failing... can't figure out why
If you would like to achieve this without having to write an equality comaparer, there is a unit testing library that you can use, called FluentAssertions,
https://fluentassertions.com/documentation/
It has many built in equality extension functions including ones for the Collections. You can install it through Nuget and its really easy to use.
Taking the example in the question above all you have to write in the end is
list1.Should().BeEquivalentTo(list2);
By default, the order matters in the two collections, however it can be changed as well.
I wrote this to test collections where the order is not important:
public static bool AreCollectionsEquivalent<T>(ICollection<T> collectionA, ICollection<T> collectionB, IEqualityComparer<T> comparer)
{
if (collectionA.Count != collectionB.Count)
return false;
foreach (var a in collectionA)
{
if (!collectionB.Any(b => comparer.Equals(a, b)))
return false;
}
return true;
}
Not as elegant as using SequenceEquals, but it works.
Of course to use it you simply do:
Assert.IsTrue(AreCollectionsEquivalent<MyType>(collectionA, collectionB, comparer));