Search in part of the list by LINQ - c#

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);

Related

Finding a permutation from list<int> using linq

This seems like it would be easy, but I have bumped into one issue after another... I have a search algorithm that requires a permutation search. I have a sql database that serves up to a web service. In my controller I have a complex search algorithm, one of the search options is to find permutations of a data field.
The data would be a list of integers like [0,0,9,3,8,7,4]... The search criterion would also come in as a list of integers like [9,4,7]... in this case the permutation exists, and it the evaluation should return true in the linq query.
So I have been attempting to write a "boolean" function that would return true or false to evaluate if a permutation exists... So far my attempts have worked except in the case where example 2 and 3 below both return true... because they are evaluated because of the single Zero, not that there are a quantity of two zeros... if that makes sense?
[0,0,9,3,8,7,4] => [9,4,7] = true
[0,0,9,3,8,7,4] => [0,0,2] = false
[0,0,9,3,8,7,4] => [9,0,0] = true
I have tried "GroupBy", which will give me a list of keys and counts, which should work... right? in #1 does the array contain 9,4, and 7... for the other two, does the array contain, two zeros and the remaining number... this is always evaluating to true but is always evaluating that the search string contains a single zero not two zeros...
Can anyone assist?
public bool IsPermutation(IEnumerable<int> list,IEnumerable<int> subList)
{
var grpListCnt = list.GroupBy(num => num).ToDictionary(grp => grp.Key, grp => grp.Count());
var subGroupCount = subList.GroupBy(num => num).ToDictionary(grp => grp.Key, grp => grp.Count());
foreach(var keypair in subGroupCount)
{
if (!(grpListCnt.ContainsKey(keypair.Key) &&
grpListCnt[keypair.Key] >= keypair.Value))
return false;
}
return true;
}
You could use simple Linq statement. Use Any and All extension and validate the combination.
// input
int[][] data = ...
int[] criteria = ...
bool matchFound = data.Any(x=> criteria.All(c=> x.Contains(c));
In case if your source data is one dimensional array, you could simply use nested part (as shown below)
// input
int[] data = ...
int[] criteria = ...
bool matchFound = criteria.All(c=> data.Contains(c));

Distinct the collection in Linq C#

I have the collection
From the collection the column name ma_position_value should not contain the same value
For Example
If the collection have 5 records, The column ma_position_value should not contain the same value from all 5 records...but it can contain same value for 2 or 3 or 4 records from the collection Atleast one column value should change.
So the main intension is ALL 5 records should not contain same value.Any one should get different value.So if all 5 is same I tried to throw a message
So I have just write a bool to return it if it is change
bool lblMa = false;
lblMa = ibusCalcWiz.iclbMssPaServiceSummary
.Where(lbusMssPaServiceSummary => lbusMssPaServiceSummary.icdoSummary.ma_position_value.IsNotNullOrEmpty()).Distinct().Count() > 1;
But it is always return true.
Just select distinct ma_position_value property values:
bool allSame = ibusCalcWiz.iclbMssPaServiceSummary
.Select(i => i.ma_position_value)
.Distinct()
.Count() == 1;
HINT: Do not use long variable names in lambda expressions. There is a rule of thumb - the bigger scope of variable usage, the bigger should be name. If scope is very small (lambda expression) then name should be very small (single letter is enough).
You can get the first one, and check if they are all equal:
// Only works if the collection is non-empty!
string first_ma_position_value = ibusCalcWiz.iclbMssPaServiceSummary.First().ma_position_value;
bool allTheSame = ibusCalcWiz.iclbMssPaServiceSummary
.All(lbusMssPaServiceSummary.icdoSummary.ma_position_value == first_ma_position_value);
or you can do the distinct, as you originally wanted, but on the value of the column instead of on the objects
bool allTheSame = ibusCalcWiz.iclbMssPaServiceSummary
.Select(lbusMssPaServiceSummary => lbusMssPaServiceSummary.icdoSummary.ma_position_value)
.Distinct()
.Count() == 1;

Determine if an int value exists once in an array

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

LINQ to find array indexes of a value

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);
}
}

check that int array contains !=0 value using lambda

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.

Categories