I want to compare two integer arrays and then print the equals out. I tried the Intersect method:
var checkingDuplicates = boughttickets.Intersect(winningtickets).Any();
and then used a if-statement:
if (checkingDuplicates == false)
{
Console.WriteLine("Sorry, You didn't win anything");
}
else
{
Console.WriteLine(checkingDuplicates);
}
However, the output always returns true with this if-statement.
I am truly sorry if i have some Spelling misstakes, my native language is not English.
Any takes a sequence of items and returns a boolean indicating if there are any items in that sequence.
You don't want to know if there are any items in that sequence, you just want to know what all of the items in that sequence are. That means don't call Any, and you'll have your sequence of the intersection of those two arrays.
First i would say read the documentation. From your comment above, you can not call .toString() on IEnumerable withou defining .tostring implementation.
Try this
var checkingDuplicates = boughttickets.Intersect(winningtickets);
if (!checkingDuplicates.Any())
{
Console.WriteLine("Sorry, You didn't win anything");
}
else
{
foreach(TICKET checkingDuplicate in checkingDuplicates)
{
Console.WriteLine("FETCH AND PRINT YOUR TICKET INFORMATION FROM TICKET OBJECT/CLASS");
}
}
In the foreach loop above TICKET is the type of object you are using on the IEnumerable lists above.
Related
I'm trying to search through a list of values, which could be any type (int, string, bool, and so-on), and I can't find a way to compare a given value against values in the list.
My code so far:
public void Countin(T data)
{
int numbersOf = 0;
Node pTmp = first;
while (pTmp != null)
{
if (pTmp.Equals(data))
{
numbersOf++
pTmp = pTmp.Next;
}
else
{
pTmp = pTmp.Next;
}
}
Console.WriteLine($"There are {numbersOf} {data} in the list.");
}
With a list of
"I" "am" "getting" "really" "really" "tired" "of" "this",
I keep getting the output of "There are 0 really in the list". And when I swap the numbersOf++ from to the 'else', I get "There are 8 really in the list."
The rest of the code works fine, it's just that "pTmp.Equals(data)" isn't doing what I think it should be doing, but I can't just use pTmp == data, due to 'data' being an element in a list.
Any help?
Every part of the above code works fine EXCEPT FOR COMPARING pTmp TO data! Nothing else needs help! I just need a way to compare the data variable to the values in the list.
FINAL EDIT:
All I had to do was change the boolean to if (Equals(pTmp.Data),data), and it worked. All I needed as an answer was 'Equals(x,y) will do what you want'. Thanks guys.
I am new to using Selenium with C#, so this might be too easy for most of you. Also, I did search on this forum and couldn't get a satisfactory response, so will go ahead and ask the problem I am trying to solve.
I want to use Assert between two different elements to check for a value. If first element finds it I want to exit the loop and pass the test, or else the second element; otherwise fail the test if not found in both.
p0 is the string that I am passing in my test and I want to check that string is there either in tranName or accName
transName is int and accName is string. But I am assigning both to same var.
Assert.That(transName.Text.Equals(p0));
Assert.That(accName.Text.Equals(p0));
Can you please suggest, how best to deal with this.
Thanks..!!
transName = driver.FindElement(By.xxxx);
if(transName.Displayed) {
Assert.That(transName.Text.Equals(p0));
}
else {
accName= driver.FindElement(By.xxxx);
if(accName.Displayed) {
Assert.That(accName.Text.Equals(p0));
}
else {
Assert.That(True.Equals(False))
}
}
You don't need to do all those conditionals. Here's an easier/shorter way to do this using LINQ, NUnit, and a custom CSS selector locator.
List<string> text = Driver.FindElements(By.CssSelector("#XXX, #YYY")).Where(e => e.Displayed).Select(e => e.Text).ToList();
CollectionAssert.Contains(text, p0);
Basically we combine the two locators into one where #XXX means an id of XXX and the comma is an OR operator. Selenium finds all the elements that match those two locators and then filters those down to those that are visible. Then it get the .Text of each of the visible elements and returns them as a List. The second line is NUnit where you can assert a string in a List<string>.
int n;
bool searchWithNumber = int.TryParse(p0, out n);
var transName = driver.FindElement(By.Id("XXX"));
if (transName.Displayed && !searchWithNumber)
{
Assert.That(tarnsName.Text.Contains(p0));
}
else if (searchWithNumber)
{
var accName = driver.FindElement(By.Id("YYY"));
if (accName.Displayed)
{
Assert.That(accName.Text.Contains(p0));
}
else
{
Assert.That(true.Equals(false));
}
}
So what I am doing above is. I am first parsing the string p0 to extract number if it has, which I am then assigning to bool. Then in the loop I am first checking if the tranName has any number then skip to else if condition, if it has text then execute the first condition.
I apologize if this is an obvious answer, but I couldn't find anything related to this behavior on StackOverflow nor on Google. I'm self-teaching c# and am writing a program that involves the use of username/password pairs. In this case, I am using .Exist() to determine if a username is already in my array of usernames.
static bool LookUpS(string targ, string[] arr)
{
if (Array.Exists(arr, e => e == targ))
{
return true;
}
else
{
return false;
}
}
The argument targ comes from the user, and the argument arr is written into the program to specify which array should be searched (this is so that I can use LookUpS on different arrays). The array that I'm testing right now is derived from a text document. I've tested to confirm that the transition from .txt to array is working properly.
Now to the actual issue. I've filled the text document in question with a few values: "Jupiter", "Neptune", "Saturn", "Mars". If I pass any of the first three into LookUpS, it returns false despite the fact that they do exist. The part I don't understand, however, is that if I pass "Mars" (or whatever the last value happens to be) into the function, it returns true like it should. If I were to remove the "Mars" value, LookUpS would say that "Saturn" is true but not the others. Can anyone offer some explanation for this? I can post a more complete picture of the program if that would help in identifying the problem.
In the comments you mention that you split the lines with \n as split separator. But on Windows \r\n is used. Hence your split string array will contain
xxxx\r
yyyy\r
lastUser
The last line does not contain a newline which will work.
That explains why your search in the array finds only the last user in your array. Pass to the split operation not \r but Environment.NewLine.ToCharArray() to remove all newline characters in string array.
Arrays have a built-in method called contains() which should do exactly what you want...
string[] array = { "Jupiter", "Neptune", "Saturn", "Mars" };
if (array.Contains("Neptune")) {
return true;
}
You could simplify it to something like this.
You can use Exists() instead of Any() if you like.
static bool LookUpS(string targ, string[] arr)
{
return (arr.Any(s => s == targ))
}
Or if you want it to be non case-sensitive:
static bool LookUpS(string targ, string[] arr)
{
return (arr.Any(e => String.Equals(e, targ, StringComparison.CurrentCultureIgnoreCase));
}
Or, as Karl suggests, you can use Contains()
static bool LookUpS(string targ, string[] arr)
{
return (arr.Contains(targ);
}
Sometimes simplifying your code can solve some problems :)
The reason that you don't need to use an if .. else to return true or false, is that the methods Any(), Exists() and Contains() return are bool, so you can just return the method call as shown in the examples
I have a sorted StringList and wanted to replace
foreach (string line3 in CardBase.cardList)
if (line3.ToLower().IndexOf((cardName + Config.EditionShortToLong(edition)).ToLower()) >= 0)
{
return true;
}
with a binarySearch, since the cardList ist rather large(~18k) and this search takes up around 80% of the time.
So I found the List.BinarySearch-Methode, but my problem is that the lines in the cardList look like this:
Brindle_Boar_(Magic_2012).c1p247924.prod
But I have no way to generate the c1p... , which is a problem cause the List.BinarySearch only finds exact matches.
How do I modify List.BinarySearch so that it finds a match if only a part of the string matches?
e. g.
searching for Brindle_Boar_(Magic_2012) should return the position of Brindle_Boar_(Magic_2012).c1p247924.prod
List.BinarySearch will return the ones complement of the index of the next item larger than the request if an exact match is not found.
So, you can do it like this (assuming you'll never get an exact match):
var key = (cardName + Config.EditionShortToLong(edition)).ToLower();
var list = CardBase.cardList;
var index = ~list.BinarySearch(key);
return index != list.Count && list[index].StartsWith(key);
BinarySearch() has an overload that takes an IComparer<T> has second parameter, implement a custom comparer and return 0 when you have a match within the string - you can use the same IndexOf() method there.
Edit:
Does a binary search make sense in your scenario? How do you determine that a certain item is "less" or "greater" than another item? Right now you only provide what would constitute a match. Only if you can answer this question, binary search applies in the first place.
You can take a look at the C5 Generic Collection Library (you can install it via NuGet also).
Use the SortedArray(T) type for your collection. It provides a handful of methods that could prove useful. You can even query for ranges of items very efficiently.
var data = new SortedArray<string>();
// query for first string greater than "Brindle_Boar_(Magic_2012)" an check if it starts
// with "Brindle_Boar_(Magic_2012)"
var a = data.RangeFrom("Brindle_Boar_(Magic_2012)").FirstOrDefault();
return a.StartsWith("Brindle_Boar_(Magic_2012)");
// query for first 5 items that start with "Brindle_Boar"
var b = data.RangeFrom("string").Take(5).Where(s => s.StartsWith("Brindle_Boar"));
// query for all items that start with "Brindle_Boar" (provided only ascii chars)
var c = data.RangeFromTo("Brindle_Boar", "Brindle_Boar~").ToList()
// query for all items that start with "Brindle_Boar", iterates until first non-match
var d = data.RangeFrom("Brindle_Boar").TakeWhile(s => s.StartsWith("Brindle_Boar"));
The RageFrom... methods perform a binary search, find the first element greater than or equal to your argument, that returns an iterator from that position
I'm trying to find a solution to this problem:
Given a IEnumerable< IEnumerable< int>> I need a method/algorithm that returns the input, but in case of several IEnmerable< int> with the same elements only one per coincidence/group is returned.
ex.
IEnumerable<IEnumerable<int>> seqs = new[]
{
new[]{2,3,4}, // #0
new[]{1,2,4}, // #1 - equals #3
new[]{3,1,4}, // #2
new[]{4,1,2} // #3 - equals #1
};
"foreach seq in seqs" .. yields {#0,#1,#2} or {#0,#2,#3}
Sould I go with ..
.. some clever IEqualityComparer
.. some clever LINQ combination I havent figured out - groupby, sequenceequal ..?
.. some seq->HashSet stuff
.. what not. Anything will help
I'll be able to solve it by good'n'old programming but inspiration is always appreciated.
Here's a slightly simpler version of digEmAll's answer:
var result = seqs.Select(x => new HashSet<int>(x))
.Distinct(HashSet<int>.CreateSetComparer());
Given that you want to treat the elements as sets, you should have them that way to start with, IMO.
Of course this won't help if you want to maintain order within the sequences that are returned, you just don't mind which of the equal sets is returned... the above code will return an IEnumerable<HashSet<int>> which will no longer have any ordering within each sequence. (The order in which the sets are returned isn't guaranteed either, although it would be odd for them not to be return in first-seen-first-returned basis.)
It feels unlikely that this wouldn't be enough, but if you could give more details of what you really need to achieve, that would make it easier to help.
As noted in comments, this will also assume that there are no duplicates within each original source array... or at least, that they're irrelevant, so you're happy to treat { 1 } and { 1, 1, 1, 1 } as equal.
Use the correct collection type for the job. What you really want is ISet<IEnumerable<int>> with an equality comparer that will ignore the ordering of the IEnumerables.
EDITED:
You can get what you want by building your own IEqualityComparer<IEnumerable<int>> e.g.:
public class MyEqualityComparer : IEqualityComparer<IEnumerable<int>>
{
public bool Equals(IEnumerable<int> x, IEnumerable<int> y)
{
return x.OrderBy(el1 => el1).SequenceEqual(y.OrderBy(el2 => el2));
}
public int GetHashCode(IEnumerable<int> elements)
{
int hash = 0;
foreach (var el in elements)
{
hash = hash ^ el.GetHashCode();
}
return hash;
}
}
Usage:
var values = seqs.Distinct(new MyEqualityComparer()).ToList();
N.B.
this solution is slightly different from the one given by Jon Skeet.
His answer considers sublists as sets, so basically two lists like [1,2] and [1,1,1,2,2] are equal.
This solution don't, i.e. :
[1,2,1,1] is equal to [2,1,1,1] but not to [2,2,1,1], hence basically the two lists have to contain the same elements and in the same number of occurrences.