I have two-dimension array
List<List<int>> boardArray
How can I enumerate throw this array to check that it contains other value than 0 ?
I think about boardArray.Contains and ForEach ,cause it return bool value but I don't have too much experience with lambda expression :/
Please help :)
Do you want to check the inner lists or simply the entire thing for a non-zero?
boardArray.Any(list => list.Any(item => item != 0));
boardArray.Where(list => list.Any(item => item != 0));
The first line will return true/false indicating whether or not there is any list within the outer list that has a non-zero value. The second line, on the other hand, filters for the lists containing non-zero items.
if (!boardArray.SelectMany(list => list).All(i => i == 0)) {
...
}
SelectMany flattens the List<List<int>> into one sequence of ints, whereas All checks that every element matches a condition.
bool containsZero = (!boardArray.SelectMany(list => list).Any(i => i == 0))
This says From all the items in boardarray loop through all of the items inside of that and return faslse if one isn't zero, then we are inversing that false.
Related
I have a list of items:
List<Item> ItemList = new List<Item>;
Sometimes the list is only partially full or certain indices are not occupied and therefore when I iterate through the list using a foreach, it gives an error because the item is null. I want to reduce that list to those items which actually have a value. This is what I'm trying:
var FullItems = ItemList.SkipWhile(Item => Item == null).ToList();
But when I check the FullItems list, it still contains the items from ItemList that are null, so I'm just getting back the entire list that I started with.
Help?
What you are looking for here is:
var FullItems = ItemList.Where(Item => Item != null).ToList();
As per the docs on SkipWhile():
Bypasses elements in a sequence as long as a specified condition is true and then returns the remaining elements.
This is not the behavior you are looking for (I have bolded the actual behavior that you don't seem to expect/desire).
SkipWhile(i => i == null) will skip until the first non-null item. Items after that first one which are null are still ignored.
Use Where(i => i != null) to select all items that are not null.
I have a list of integers as below
List<int> myCollection = new List<int> { 2625 };
I am checking below condition
if(myCollection.Count() == 1 && myCollection.Any(number=> number == 2625))
{
// Do something
}
How can I optimize my query so that I can include both conditions single query?
Note: MyCollection may contain multiple elements hence I have used Any().
One obvious optimization would be to use List instance properties:
if(myCollection.Count == 1 && myCollection[0] == 2625))
{
// Do something
}
Actually, here you have one query. Not two. Since your collection is a list, Count() will be resolved to Count property of list. That being said, nothing actually will happen here
myCollection.Count() == 1
except from getting the value of Count.
The only query happens here
myCollection.Any(number=> number == 2625)
Furthermore, since the first condition you check if the Count is 1, if it doesn't, then Any wouldn't be evaluated at all. (This happens because we make use of &&).
I'm not sure why you want to
Optimize this, but if there is a single element why use .Any().
You could simply do
if(myCollection.Count() == 1 && myCollection.Single() == 2625)
{
// Do something
}
I know you can use Any, Exists, and Single with LINQ but can't quite get this to work. I need to do a lookup based on an id to see if it's in the array and make sure that there is only ONE match on that value. because if there are 2 it's gonna cause an issue..the requirement that I'm checking is that the array only has one and only one of each ID in the array.
Here's what I tried
if(someIntArray.Single(item => item = 3)
//... we found the value 8 in the array only once so now we can be confident and do something
Here's how I would solve this:
if (someIntArray.Count(item => item == 3) == 1)
{
//only one '3' found in the array
...
}
I created a One() extension method set for just this situation:
public static bool One<T>(this IEnumerable<T> sequence)
{
var enumerator = sequence.GetEnumerator();
return enumerator.MoveNext() && !enumerator.MoveNext();
}
public static bool One<T>(this IEnumerable<T> sequence, Func<T, bool> predicate)
{
return sequence.Where(predicate).One();
}
//usage
if (someIntArray.One(item => item == 3)) ...
The problem with Single() is that it throws an exception if there isn't exactly one element. You can wrap it in a try-catch, but these are cleaner, and more efficient than Count() in most cases where there's more than one matching element. Unfortunately, there's no way around having to check the entire array to verify that there are either no elements or only one that matches a predicate, but this will at least "fail fast" if there are two or more, where Count() will always evaluate the entire Enumerable whether there's one matching element or fifty.
I think you're overthinking this.
var targetNumber = 3;
var hasExactlyOne = someIntArray.Count(i => i == targetNumber) == 1;
Using LINQ expression:
var duplicates = from i in new int[] { 2,3,4,4,5,5 }
group i by i into g
where g.Count() > 1
select g.Key
Results:
{4,5}
And of course you could check duplicates.Count() > 0 or log the ones that are a problem or whatever you need to do.
got it working:
if(someIntArray.Single(item => item = 3) > 0)
doh
I want to know if there's a way to search from a specific index in LINQ
This is what i want to do for example :
//search after the 4th element if exist any true
bool result = myList.Any(a=>a.flagTodo)
// in my case I want to do like: myList.where(a=>a.index >4).Any(a=>a.flagTodo)
there's any way to do it in the same linq ?
You can use Enumerable.Skip to bypass specified number of elements in sequence:
bool result = myList.Skip(4).Any(a => a.flagTodo);
BTW you don't need to verify list length - if there is less than 4 items, result will be false - Skip(4) will return empty sequence. And Any returns false because none of elements in sequence satisfies condition (sequence is empty).
You can skip the first 4 elements.
bool result = myList.Skip(4).Any(a => a.flagTodo);
But you need to check on your list length first before calling this statement.
Either use Skip as others have mentioned or pass the index so that you can use it in Any
bool result = myList.Select((obj, index) => new { obj, index })
.Any(x => x.index > 4 && x.obj.flagTodo);
Assuming I have the following string array:
string[] str = new string[] {"max", "min", "avg", "max", "avg", "min"}
Is it possbile to use LINQ to get a list of indexes that match one string?
As an example, I would like to search for the string "avg" and get a list containing
2, 4
meaning that "avg" can be found at str[2] and str[4].
.Select has a seldom-used overload that produces an index. You can use it like this:
str.Select((s, i) => new {i, s})
.Where(t => t.s == "avg")
.Select(t => t.i)
.ToList()
The result will be a list containing 2 and 4.
Documentation here
You can do it like this:
str.Select((v,i) => new {Index = i, Value = v}) // Pair up values and indexes
.Where(p => p.Value == "avg") // Do the filtering
.Select(p => p.Index); // Keep the index and drop the value
The key step is using the overload of Select that supplies the current index to your functor.
You can use the overload of Enumerable.Select that passes the index and then use Enumerable.Where on an anonymous type:
List<int> result = str.Select((s, index) => new { s, index })
.Where(x => x.s== "avg")
.Select(x => x.index)
.ToList();
If you just want to find the first/last index, you have also the builtin methods List.IndexOf and List.LastIndexOf:
int firstIndex = str.IndexOf("avg");
int lastIndex = str.LastIndexOf("avg");
(or you can use this overload that take a start index to specify the start position)
First off, your code doesn't actually iterate over the list twice, it only iterates it once.
That said, your Select is really just getting a sequence of all of the indexes; that is more easily done with Enumerable.Range:
var result = Enumerable.Range(0, str.Count)
.Where(i => str[i] == "avg")
.ToList();
Understanding why the list isn't actually iterated twice will take some getting used to. I'll try to give a basic explanation.
You should think of most of the LINQ methods, such as Select and Where as a pipeline. Each method does some tiny bit of work. In the case of Select you give it a method, and it essentially says, "Whenever someone asks me for my next item I'll first ask my input sequence for an item, then use the method I have to convert it into something else, and then give that item to whoever is using me." Where, more or less, is saying, "whenever someone asks me for an item I'll ask my input sequence for an item, if the function say it's good I'll pass it on, if not I'll keep asking for items until I get one that passes."
So when you chain them what happens is ToList asks for the first item, it goes to Where to as it for it's first item, Where goes to Select and asks it for it's first item, Select goes to the list to ask it for its first item. The list then provides it's first item. Select then transforms that item into what it needs to spit out (in this case, just the int 0) and gives it to Where. Where takes that item and runs it's function which determine's that it's true and so spits out 0 to ToList, which adds it to the list. That whole thing then happens 9 more times. This means that Select will end up asking for each item from the list exactly once, and it will feed each of its results directly to Where, which will feed the results that "pass the test" directly to ToList, which stores them in a list. All of the LINQ methods are carefully designed to only ever iterate the source sequence once (when they are iterated once).
Note that, while this seems complicated at first to you, it's actually pretty easy for the computer to do all of this. It's not actually as performance intensive as it may seem at first.
While you could use a combination of Select and Where, this is likely a good candidate for making your own function:
public static IEnumerable<int> Indexes<T>(IEnumerable<T> source, T itemToFind)
{
if (source == null)
throw new ArgumentNullException("source");
int i = 0;
foreach (T item in source)
{
if (object.Equals(itemToFind, item))
{
yield return i;
}
i++;
}
}
You need a combined select and where operator, comparing to accepted answer this will be cheaper, since won't require intermediate objects:
public static IEnumerable<TResult> SelectWhere<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, bool> filter, Func<TSource, int, TResult> selector)
{
int index = -1;
foreach (var s in source)
{
checked{ ++index; }
if (filter(s))
yield return selector(s, index);
}
}