Getting Distinct count from the list - c#

I am trying to find the number of unique dates in my list.
IEnumerable<T>
public int CountUniqueDate()
{
return _items.DistinctBy(i => i.DateMeasured).Count();
}
I think, this function will tell me the count of the unique dates in the list.
Now, from the other file, I try to retrieve the value
Either I want the count or the condition which will tell whether it is one or not.
So I try this to check whether the count is 1 or not.
But, here i get compilation error.
If I do var ans, then I get a full list.
List<T> li;
bool ans= li.Where(x => x.Measures.CountUniqueDate() == 1);
Can anyone please help me.
I wanna check, if the CountUniqueDate returns value 1 or not.

The WHERE CLAUSE doesnt return a boolean but an IEnumerable(Of TSource)

If you wan't to check if the there is one with count = 1 or not you might use
bool ans= li.Any(x => x.Measures.CountUniqueDate() == 1);

Change your method to be an extension method like this
public static class Extensions
{
public static int CountUniqueDate(this List<Measure> items) //<= measure is your T type
{
return items.DistinctBy(i => i.DateMeasured).Count();
}
}
then you can call it like this:
List<Measure> li = YourData;
bool ans= li.CountUniqueDate() == 1;

Related

Best way to get range from 1 to n-1 with linq

I would like to use linq to query a sorted List with n elements, so that I can get elemnts between first and last.
I have tried the following, but it seems not to look good:
var result1 = myList.Skip(1).Take(myList.Count()-2);
var result2 = myList.GetRange(1, myList.Count()-2);
Are there other ways to achieve the goal?
You have to take into account that LinQ will perform as many loops as necessary to achieve its purpose. Sometimes, writing your own loop will gets better results. Then encapsulate your loop into an extension methods and you get your one line solution:
namespace System.Linq
{
public static class MyLinqExtensions
{
public static IEnumerable<T> Range<T>(this IEnumerable<T> input, int start, int end)
{
int i = 0;
foreach(var item in input)
{
if(i < start) continue;
if(i > end) break;
yield return item;
i++;
}
}
}
}
This is Best Way
var result1 = myList.Skip(1).Take(myList.Count()-2);
This Best way of Linq Query Because Getrange does not accept Negative Numer.
For Example:
MyList is No record then Skip And Take method execute Linq query out put is empty list result but Getrange method throw exception for "Non-negative number required.
Parameter name: count"

C# FindIndex with parameters

I'm currently patching my game that i recently released.
I have a list of a class, which is called AppliedEffects. The list made from that class is named appliedEffects.
I want to access this list and find a specific value in an index, and then make a bool true or false depending of if that value exists in the list. It is for a powerup system, where the list is all the powerups currently active. The code for shooting bullets for instance, will then search if there is an item in the list with the ID of 1, because that is the ID of having the double bullets powerup.
I have come this far, and only have a small problem:
int ndx = PlayerStatus.appliedEffects.FindIndex(PlayerStatus.FindAE(XX,1);
where XX is, I don't know what to put. I edited this:
int ndx = Books.FindIndex(FindComputer);
private static bool FindComputer(Book bk)
{
if (bk.Genre == "Computer")
{
return true;
}
else
{
return false;
}
}
Because in the code example, I could not send in which parameter I wanted to search for. The edited code looks like this:
public static bool FindAE(AppliedEffects ae, int id)
{
if (ae.id == id)
{
return true;
}
else
{
return false;
}
}
I create an int, that will get the index of the list where the item with the value of ID 1 exists, then if that value is 1, because the ID is 1, it will set a bool to true, and false if not.
I wanted to send in a parameter for the ID, which the example does not, so that I can reuse the function for other ID checks. But then when I enter the parameter, I don't know what to put as appliedEffect (that's why I put XX).
I have also tried this:
if (PlayerStatus.appliedEffects.Exists(x => x.id == 1))
{
PlayerStatus.doubleBullets = true;
}
which did not work, no clue why. I don't fully understand the concepts of the .Exists and .FindIndex, so maybe that's why I don't know how to use it.
Basically I just want to be able to check if there is an item with a specific ID in the list, so that the game will know that I have the specific powerup and can set a bool to true and then false.
Note: ID is not index, ID is an int in my AppliedEffects class that knows which powerup it is.
I'm a little tired so if there's any thoughts/concerns, please write in the thread, I'll subscribe to the thread.
Note that FindIndex will return -1 if the requested element is not found. Therefore, you would have to do something like so:
if(PlayerStatus.appliedEffects.FindIndex(ae => PlayerStatus.FindAE(ae, 1)) != -1)
{
PlayerStatus.doubleBullets = true;
}
It would probably make more sense in your situation to use Exists, like you noted. Try this:
if(PlayerStatus.appliedEffects.Exists(ae => PlayerStatus.FindAE(ae, 1)))
{
PlayerStatus.doubleBullets = true;
}
int ndx = PlayerStatus.appliedEffects.FindIndex(ae => PlayerStatus.FindAE(ae, 1));
The parameter to FindIndex is a method/lambda with one argument. In this case, a lambda is created which takes a single parameter ae, and returns FindAE(ae, 1).
The FindAE method isn't necessary. It might be easier to do this:
int ndx = PlayerStatus.appliedEffects.FindIndex(ae => ae.index == 1);

Check if list contains element that contains a string and get that element

While searching for an answer to this question, I've run into similar ones utilizing LINQ but I haven't been able to fully understand them (and thus, implement them), as I'm not familiarized with it. What I would like to, basically, is this:
Check if any element of a list contains a specific string.
If it does, get that element.
I honestly don't know how I would go about doing that. What I can come up with is this (not working, of course):
if (myList.Contains(myString))
string element = myList.ElementAt(myList.IndexOf(myString));
I know WHY it does not work:
myList.Contains() does not return true, since it will check for if a whole element of the list matches the string I specified.
myList.IndexOf() will not find an occurrence, since, as it is the case again, it will check for an element matching the string.
Still, I have no clue how to solve this problem, but I figure I'll have to use LINQ as suggested in similar questions to mine. That being said, if that's the case here, I'd like for the answerer to explain to me the use of LINQ in their example (as I said, I haven't bothered with it in my time with C#). Thank you in advance guys (and gals?).
EDIT: I have come up with a solution; just loop through the list, check if current element contains the string and then set a string equal to the current element. I'm wondering, though, is there a more efficient way than this?
string myString = "bla";
string element = "";
for (int i = 0; i < myList.Count; i++)
{
if (myList[i].Contains(myString))
element = myList[i];
}
You should be able to use Linq here:
var matchingvalues = myList
.Where(stringToCheck => stringToCheck.Contains(myString));
If you simply wish to return the first matching item:
var match = myList
.FirstOrDefault(stringToCheck => stringToCheck.Contains(myString));
if(match != null)
//Do stuff
The basic answer is: you need to iterate through loop and check any element contains the specified string.
So, let's say the code is:
foreach(string item in myList)
{
if(item.Contains(myString))
return item;
}
The equivalent, but terse, code is:
mylist.Where(x => x.Contains(myString)).FirstOrDefault();
Here, x is a parameter that acts like "item" in the above code.
string result = myList.FirstOrDefault(x => x == myString)
if(result != null)
{
//found
}
for (int i = 0; i < myList.Length; i++)
{
if (myList[i].Contains(myString)) // (you use the word "contains". either equals or indexof might be appropriate)
{
return i;
}
}
Old fashion loops are almost always the fastest.
If you want a list of strings containing your string:
var newList = myList.Where(x => x.Contains(myString)).ToList();
Another option is to use Linq FirstOrDefault
var element = myList.Where(x => x.Contains(myString)).FirstOrDefault();
Keep in mind that Contains method is case sensitive.
You could use Linq's FirstOrDefault extension method:
string element = myList.FirstOrDefault(s => s.Contains(myString));
This will return the fist element that contains the substring myString, or null if no such element is found.
If all you need is the index, use the List<T> class's FindIndex method:
int index = myList.FindIndex(s => s.Contains(myString));
This will return the the index of fist element that contains the substring myString, or -1 if no such element is found.
Many good answers here, but I use a simple one using Exists, as below:
foreach (var setting in FullList)
{
if(cleanList.Exists(x => x.ProcedureName == setting.ProcedureName))
setting.IsActive = true; // do you business logic here
else
setting.IsActive = false;
updateList.Add(setting);
}
You should be able to use something like this, it has worked okay for me:
var valuesToMatch = yourList.Where(stringCheck => stringCheck.Contains(myString));
or something like this, if you need to look where it doesn't match.
var valuesToMatch = yourList.Where(stringCheck => !stringCheck.Contains(myString));
you can use
var match=myList.Where(item=>item.Contains("Required String"));
foreach(var i in match)
{
//do something with the matched items
}
LINQ provides you with capabilities to "query" any collection of data. You can use syntax like a database query (select, where, etc) on a collection (here the collection (list) of strings).
so you are doing like "get me items from the list Where it satisfies a given condition"
inside the Where you are using a "lambda expression"
to tell briefly lambda expression is something like (input parameter => return value)
so for a parameter "item", it returns "item.Contains("required string")" . So it returns true if the item contains the string and thereby it gets selected from the list since it satisfied the condition.
To keep it simple use this;
foreach(string item in myList)//Iterate through each item.
{
if(item.Contains("Search Term")//True if the item contains search pattern.
{
return item;//Return the matched item.
}
}
Alternatively,to do this with for loop,use this;
for (int iterator = 0; iterator < myList.Count; iterator++)
{
if (myList[iterator].Contains("String Pattern"))
{
return myList[iterator];
}
}
It is possible to combine Any, Where, First and FirstOrDefault; or just place the predicate in any of those methods depending on what is needed.
You should probably avoid using First unless you want to have an exception thrown when no match is found. FirstOrDefault is usually the better option as long as you know it will return the type's default if no match is found (string's default is null, int is 0, bool is false, etc).
using System.Collections.Generic;
using System.Linq;
bool exists;
string firstMatch;
IEnumerable<string> matchingList;
var myList = new List<string>() { "foo", "bar", "foobar" };
exists = myList.Any(x => x.Contains("o"));
// exists => true
firstMatch = myList.FirstOrDefault(x => x.Contains("o"));
firstMatch = myList.First(x => x.Contains("o"));
// firstMatch => "foo"
firstMatch = myList.First(x => x.Contains("dark side"));
// throws exception because no element contains "dark side"
firstMatch = myList.FirstOrDefault(x => x.Contains("dark side"));
// firstMatch => null
matchingList = myList.Where(x => x.Contains("o"));
// matchingList => { "foo", "foobar" }
Test this code # https://rextester.com/TXDL57489
I have not seen bool option in other answers so I hope below code will help someone.
Just use Any()
string myString = "test";
bool exists = myList
.Where(w => w.COLUMN_TO_CHECK.Contains(myString)).Any();
You can check the list is empty or not in multiple ways.
1)Check list is null and then check count is greater than zero like below:-
if(myList!=null && myList.Count>0)
{
//List has more than one record.
}
2)Check list null and count greater than zero using linq query like below:-
if(myList!=null && myList.Count>0)
{
//List has more than one record.
}

Is this achievable with a single LINQ query?

Suppose I have a given object of type IEnumerable<string> which is the return value of method SomeMethod(), and which contains no repeated elements. I would like to be able to "zip" the following lines in a single LINQ query:
IEnumerable<string> someList = SomeMethod();
if (someList.Contains(givenString))
{
return (someList.Where(givenString));
}
else
{
return (someList);
}
Edit: I mistakenly used Single instead of First. Corrected now.
I know I can "zip" this by using the ternary operator, but that's just not the point. I would just list to be able to achieve this with a single line. Is that possible?
This will return items with given string or all items if given is not present in the list:
someList.Where(i => i == givenString || !someList.Contains(givenString))
The nature of your desired output requires that you either make two requests for the data, like you are now, or buffer the non-matches to return if no matches are found. The later would be especially useful in cases where actually getting the data is a relatively expensive call (eg: database query or WCF service). The buffering method would look like this:
static IEnumerable<T> AllIfNone<T>(this IEnumerable<T> source,
Func<T, bool> predicate)
{
//argument checking ignored for sample purposes
var buffer = new List<T>();
bool foundFirst = false;
foreach (var item in source)
{
if (predicate(item))
{
foundFirst = true;
yield return item;
}
else if (!foundFirst)
{
buffer.Add(item);
}
}
if (!foundFirst)
{
foreach (var item in buffer)
{
yield return item;
}
}
}
The laziness of this method is either that of Where or ToList depending on if the collection contains a match or not. If it does, you should get execution similar to Where. If not, you will get roughly the execution of calling ToList (with the overhead of all the failed filter checks) and iterating the result.
What is wrong with the ternary operator?
someList.Any(s => s == givenString) ? someList.Where(s => s == givenString) : someList;
It would be better to do the Where followed by the Any but I can't think of how to one-line that.
var reducedEnumerable = someList.Where(s => s == givenString);
return reducedEnumerable.Any() ? reducedEnumerable : someList;
It is not possible to change the return type on the method, which is what you're asking. The first condition returns a string and the second condition returns a collection of strings.
Just return the IEnumerable<string> collection, and call Single on the return value like this:
string test = ReturnCollectionOfStrings().Single(x => x == "test");

Explain how delegates work in the following code?

I am curious on how the following code works, especially the part the contains the delegate stuff since I am new to it. Also, are there any bottlenecks in the code, for example, would using a SortedDictionary be better than using a List and then sorting it using LINQ? Ok, here is the code:
public class ColorManager
{
private List<ColorData> colorCodes = new List<ColorData>();
public List<ColorData> ColorCodes
{
get
{
var sortList = from a in this.colorCodes
orderby a.colorCode ascending
select a;
return sortList.ToList();
}
}
public void FillData(DataTable table)
{
for(int row = 0; row < table.Rows.Count; row++)
{
ColorData cData = new ColorData();
string name = table.Rows[row]["Color"].ToString().Trim();
if(!this.colorCodes.Exists(
delegate(ColorData e)
{
return e.ColorCode == name;
}))
{
cData.Add(table.Rows[row]["Color"].ToString());
this.colorCodes.Add(cData);
}
else
{
this.colorCodes.Find(
delegate(ColorData e)
{
return e.ColorCode == name;
}).Count++;
}
}
}
}
I am curious on how the following code works, especially the part the contains the delegate stuff since I am new to it.
First take a look at this ColorCodes property accessor:
var sortList = from a in this.colorCodes
orderby a.colorCode ascending
select a;
It returns a list of all the color codes (this.colorCodes) in ascending order (...orderby a.colorCode ascending). Simple so far. How about the meatier FillData method?
First, we'll loop over every row in this table:
for(int row = 0; row < table.Rows.Count; row++)
{
Then, we're going to look at the Color column of the current row.
ColorData cData = new ColorData();
string name = table.Rows[row]["Color"].ToString().Trim();
If that column has no match in our list of color codes, this if condition is true. The Exists method takes a single-argument function that returns a bool, which is what this anonymous delegate is: a single-argument (ColorData e) function that returns a boolean (e.ColorCode == name). It gets negated (!this.[...]), so if a match is found, the condition is false.
if(!this.colorCodes.Exists(
delegate(ColorData e)
{
return e.ColorCode == name;
}))
{
cData.Add(table.Rows[row]["Color"].ToString());
this.colorCodes.Add(cData);
}
Otherwise, if there's a match, find the name using another anonymous delegate, and add one to the count of items of that color.
else
{
this.colorCodes.Find(
delegate(ColorData e)
{
return e.ColorCode == name;
}).Count++;
}
}
Note that this code is somewhat inefficient, since the two different anonymous delegates really do the same thing and could be shared.
Actually, there are more delegates there than you expect. The LINQ query:
var sortList = from a in this.colorCodes
orderby a.colorCode ascending
select a;
is actually:
var sortList = this.colorCodes.OrderBy(a => a.colorCode);
which (for LINQ-to-Objects) is the same as:
var sortList = this.colorCodes.OrderBy(delegate (ColorData a) {
return a.colorCode;
})
This uses a delegate to identify the item to sort by - i.e. "given a ColorData, I'll give you the colorCode". Note that many select uses also involve a delegate, but not in this case (the trivial select a is removed by the compiler).
In the code:
if(!this.colorCodes.Exists(
delegate(ColorData e)
{
return e.ColorCode == name;
}))
we are using a predicate; "given a ColorData, I'll tell you whether it is a match, by testing the name for equality". Note that name here is "captured" into the delegate, which involves some fairly complex compiler tricks (I won't describe them).
Re efficiencies; it is hard to be sure, but perhaps:
Dictionary<string, ColorData> items = new Dictionary<string, ColorData>();
foreach(DataRow row in table.Rows) {
string name = row["Color"].ToString().Trim();
ColorData cData;
if (items.TryGetValue(name, out cData)) {
cData.Count++;
} else {
cData.Add(name);
colorCodes.Add(cData);
items.Add(name, cData);
}
}
This avoids lots of duplication, and uses a dictionary to find values rather than constantly using Contains/Find. In many cases, a LINQ GroupBy might have helped, but not in this case, perhaps.
Its an anonymous delegate that serves as the selection criteria for the find expression. In words, if the color is equal to the color given by name, it will return true and Find will add this to the IEnumerable that it is generating. If it returns false, Find will not contain it. It can be written more succinctly as
p => p.ColorCode == name
Exists and Find are generic extension methods. They for for each loop over each item in the collection. Passing the delegate a parameter (defined like "(ColorData e)"), and returning a boolean.
Delegates:
The delegates in this example are implementing a Func method. Basically, what you're doing, is creating a method on the fly that takes a ColorData argument, and returns a bool.
This lets you do your Exists() and Find() calls on every member of your IEnumerable collection for checking and filtering.
As for Sorted Dictionary:
If this is the only place you're using it, you'd be better off using SortedDictionary, since you wouldn't be resorting it constantly. Right now, every time you call ColorCodes you're resorting. A SortedDictionary would be constantly sorted.

Categories