Assert that a collection does not contain any item in another collection - c#

Consider this code:
string[] myCollection = { "a", "b", "c", "d" };
string[] anotherCollection = { "c", "d" };
I want to test that myCollection does not contain any item of anotherCollection. How can I achieve that in NUnit?
I tried these:
CollectionAssert.DoesNotContain(anotherCollection, myCollection);
Assert.That(myCollection, Has.No.Member(anotherCollection));
...but the problem is that these functions operate on a single entity and I did not find any way to let them work with arrays.

To assert that a collection does not contain any of a set of items, we can check that the intersection of another collection is empty using LINQ:
string[] subject = { "a", "b", "c", "d" };
string[] forbidden = { "c", "d" };
Assert.IsEmpty(subject.Intersect(forbidden));
// Or:
Assert.That(subject.Intersect(forbidden), Is.Empty);
The test shown above will fail because both collections contain the values "c" and "d".
If we want the test to fail only when the collection contains all of the prohibited items:
Assert.That(subject.Intersect(forbidden), Is.Not.EquivalentTo(forbidden));
// Or:
Assert.That(subject, Is.Not.SupersetOf(forbidden));

Related

Fastest way to cross check 2 Lists with eachother

What would be the most effective method to check whether a string value from list1 exists in list2?
Pseudo Code example
StringList List1 = {"a", "b", "c", "d"};
StringList List2 = {"d", "c", "b", "a"};
foreach (string a in List1)
{
foreach (string b in List2)
{
if(a==b)
{
WriteLine("match");
}
}
}
This method is far too slow to be the best solution, the platform I am using is BI#, a derivative off C#. Array.Exists does not exist in this current library.
You can use Intersect:
var allIntersections = List1.Intersect(List2);
foreach(string match in allIntersections)
Console.WriteLine(match);
If you just want to know if at least one intersects:
bool anyExist = allIntersections.Any();
Converting the List into a comma deliminated string, allows to use a standard InString function in this case a function called StringContains;
foreach (string a in List1)
{
if(StringContains(a, NewString))
{
WriteLine("Match");
}
}
bool flag= list2.Except(list1).Any();
This will be true if list1 doesn't contains all from list2.

LINQ - Output true/false "checklist" of items from list A contained in list B

I have two lists:
List<string> list1 = new List<string>(){ "a", "b", "c", "d" };
List<string> list2 = new List<string>(){ "b", "d", "e" };
I want to find all items of list1 that match the items in list2, and generate a List list3 that contains:
{ false, true, false, true }
How can I go about that?
Thanks in advance,
Wavy
This is all it takes:
list1.Select(str => list2.Contains(str)).ToList();
#Balazs answer is correct, but you should know that Contains operation on list is O(n) operation. And if lists are pretty big, then creating new list will be O(n*m) operation, which might be pretty slow. If you want to check whether some value is among other values, best way is having some hash-based structure which has O(1) for Contains operation. So, just put second list values to HashSet
var hashSet = new HashSet<string>(list2);
var result = list1.Select(hashSet.Contains).ToList();

eliminating duplicated lists from a nested list c#

i have a nested list that contains a set of lists, some of these lists are duplicated, i wanna just make a second list without duplicated lists. i tried this :
List<List<string>> liste1 = new List<List<string>>();
List<List<string>> liste2 = new List<List<string>>();
List<string> l1 = new List<string> { "a", "b", "c" };
List<string> l2 = new List<string> { "h", "x", "g" };
List<string> l3 = new List<string> { "a", "b", "c" };
List<string> l4 = new List<string> { "z", "t", "n" };
liste1.Add(l1);
liste1.Add(l2);
liste1.Add(l3);
liste1.Add(l4);
foreach (List<string> lis in liste1)
{
if(!liste2.Contains(lis))
{
liste2.Add(lis);
}
}
it seems easy but its not working, any help will be appreciated. Thx.
Using Linq, you could achieve this.
You could take help of extension methods and look for SequentialEqual of two lists. If the order is not important use Except extension (something like ...s.Except(x).Any()).
var liste2= liste1.Where((x,i)=> !liste1.Skip(i+1).Any(s=>s.SequenceEqual(x)));
Check this Demo
You are checking for reference equality. Instead of using Contains try this substitution
//if (!liste2.Contains(lis))
if(!liste2.Any(subList => subList.SequenceEqual(lis)))
SequenceEqual is an extension method on IEnumerable<T>. I think you will need a using statement importing the System.Linq namespace.
If you dont want to test that the child lists are not sequence-equal, but set-equal (i.e. order is not important), then consider using an implementation of ISet<T> like HashSet<int> instead of List<int>.

Dynamicly remove and add another letter from a List<> keeping alphabetical order

I have this predefined string array :
string[] SkippedAreasArray = new string[] {"A", "B", "C", "D", "E", "F", "G",
"H", "I", "J", "K", "L", "M", "N", "O", "P", "Q"};
And according to an user input I populate a List<string> like this :
List<String> UsedAreas = new List<String>();
int RangeOfInput = (int)entity.AreasCnt;
UsedAreas = SkippedAreasArray.ToList().GetRange(0, RangeOfInput);
Also from an user input I get another string containing non-duplicated letters from A to Q (like in SkippedAreasArray).
The array is formed like this :
SkippedAreasFromForm = (txtSkippedAreas.Text).ToUpper().Split(',');
What I do is first - sorting the SkippedAreasFromForm :
Array.Sort<string>(SkippedAreasFromForm);
And then I need the following :
foreach (string tempAreaValue in SkippedAreasFromForm)
{
if (UsedAreas.Contains(tempAreaValue))
{
}
else
{
}
}
if the List<> UsedAreas contains the letter that is checked I want to remove this letter from the List and at the same time to add the next letter that follows in alphabetical order.
P.S
I see now that my goal is not clear here so I'll explain the meaning of this :
SkippedAreasFromForm is an user input that should be validated and that's the idea to want this algorithm. If in some case if (UsedAreas.Contains(tempAreaValue)) returns false then the input is wrong and I need to return error message.
You can use LINQ to Objects to achieve that without looping:
UsedAreas = SkippedAreasArray.Except(SkippedAreasFromForm)
.OrderBy(e => e)
.Take(RangeOfInput)
.ToList();
It's taking RangeOfInput elements from SkippedAreasArray that are not in SkippedAreasFromForm. Result is List<string>.
Update
You can check your error message condition that way:
if(SkippedAreasFromForm.Except(SkippedAreasArray.Take(RangeOfInput)).Any())
{
// incorrect user input
}
IEnumerable<string> usedAreas = SkippedAreasArray.Take(RangeOfInput);
IEnumerable<string> skippedAreasFromForm = (txtSkippedAreas.Text).ToUpper()
.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
IEnumerable<string> invalids = skippedAreasFromForm.Except(usedAreas);
if (invalids.Any())
MessageBox.Show(string.Format("These are invalid: [{0}]",
string.Join(",", invalids.OrderBy(sa => sa))));

Add array to an array - one by one

I would like to add arrays to a list or multidimensional array (not all at once...). But I dont really understand why this should be that hard.
Lets say I have this:
string[] a = { "h", "b"};
string[] b = { "c", "a", "i" };
string[] c = { "out", "in", "file", "test" };
ArrayList x = null;
x.Add(a); //error: Object reference not set to an instance of an object.
x.Add(b);
x.Add(c);
Can I use instead of the ArrayList maybe
string[,] x = null;
But there is no option to .Add
Lets say I have an unknown amount of string[]´s with an unknown size - how do I add them to a List/multidimensional array? And again: I would like to add these string[]´s one by one. Any ideas?
You are getting an NullReferenceException because your list is not initialized:
string[] a = { "h", "b"};
string[] b = { "c", "a", "i" };
string[] c = { "out", "in", "file", "test" };
IList<string[]> x = new List<string[]>;
x.Add(a);
x.Add(b);
x.Add(c);
This assumes that you are constructing a 2-D structure. If you would like to "flatten" your arrays into a single list of strings, create a list, and use its List.AddRange method instead.
you haven't made an instance of the ArrayList you want to store the string arrays in. Try adding
ArrayList x = new ArrayList();
x.Add(a);
...
...
ArrayList x = null;
x.Add(a);
That would work if:
You create an instance of ArrayList:
ArrayList x = new ArrayList();
all you were doing was to declare a local variable.
You are careful to separate ArrayList.Add from ArrayList.AddRange. The former adds a single object. In your case the first element (after the first Add) would be itself an array. To access the "h" would need x[0][0]. AddRange takes each passed collection element in term and adds it to the collection. Thus getting the "h" would be x[0] and "b" would be x[1].
I think you want:
string[] a = { "h", "b"};
string[] b = { "c", "a", "i" };
string[] c = { "out", "in", "file", "test" };
ArrayList x = new ArrayList();
x.AddRange(a);
x.AddRange(b);
x.AddRange(c);
The keyword null essentially means "no object". Therefore when you write x.Add(a) you are trying to call the Add method on something that isn't there.
You need to initialize your list first, which puts something in the box labelled x:
ArrayList x = new ArrayList();
You can now call x.add(a) and your code will work as expected.
You are missing new for ArrayList so you should do it like this:
ArrayList x = new ArrayList();
x.AddRange(a);
x.AddRange(b);
x.AddRange(c);
You can't can't use array in Add method , you will not get any compile error but then while you will access the object you will get just ToString on type that means if you say:
string[] a = { "h", "b"};
x.Add(a);
and then try to loop through the elements like:
foreach (var item in x)
{
Console.WriteLine(item);
}
you will the result: System.String[] and I hope you don't want that, so you need to use AddRange method which takes an argument of type ICollection, so you say:
x.AddRange(a);
and if you do a loop on array list like:
foreach (var item in x)
{
Console.WriteLine(item);
}
you will get the output,
h
b
One way to do it is:
List<List<string>> list = new List<List<string>>();
list.Add(new List<string>(){
"str1", "str2", "..."
});
be sure to include: using System.Collections.Generic;

Categories