CS7036 C# in Array.FindAll + Lambda - c#

I want to change A to B.
A is
int[] list = { 1, 2, 3, 4, 5 };
List<int> evenList = new List<int>();
foreach ( var item in list )
{
if (item % 2 == 0)
{
evenList.Add(item);
}
}
foreach ( var item in evenList )
{
Console.Write(item + ",");
}
and B is
List<int> evenList = list.FindAll((elem) => elem % 2 == 0);
evenList.ForEach(elem) => { Console.Write(elem + ","); } );
but at B, I faced an Error like this:
CS7036 C# There is no argument given that corresponds to the required
formal parameter 'match' of 'Array.FindAll<T>(T[], Predicate<T>)'
ps. I added using
using System;
using System.Collections.Generic;
Is there anything that I forgot?

int[] list = { 1, 2, 3, 4, 5 };
List<int> evenList = Array.FindAll(list, elem => elem % 2 == 0).ToList();
evenList.ForEach(elem => { Console.Write(elem + ","); } );
Array.FindAll is not extension method, so you simply can't call list.FindAll()
Array do not have ForEach, so you need to cast evenList ToList()

That's because Array.FindAll is static, so you should call it like this:
var NewList = Array.FindAll(list, (elem) => elem %2 == 0);
From MSDN:
Syntax:
public static T[] FindAll<T>(
T[] array,
Predicate<T> match
)
link: https://msdn.microsoft.com/en-us/library/1kkxfxdd(v=vs.110).aspx
Cheers
EDIT:
Programming is not a guessing game where you try to write code without respecting the proper syntax.
Here's what you should be doing:
int[] list = { 1, 2, 3, 4, 5 };
List<int> evenList = Array.FindAll(list, elem => elem % 2 == 0).ToList();
Console.Write(string.Join(",", evenList) );

Any reason why you aren't using Linq? It is newer and applies to any type of collection, not just int[].
using System.Linq;
Console.Write(list
.Where(i => i % 2 == 0)
.Select(i => i.ToString())
.DefaultIfEmpty()
.Aggregate((a, b) => a + "," + b));
Performancewise, this will execute at the same complexity as your for loop, but it will likely be slightly slower overall (though I actually think it won't be that much slower). Linq evaluates lazily which helps here.

Related

how to find out existance of specific pattern in a list of integers by help of Linq. C#

How to determine a range in a list of integer follow specific pattern.
For example, we have a list like this:
List<int> ints = new List<int>(){4,5,2,6,8,4,5,6,5,6,8,9,9};
Exists and Any could check if an element satisfies specific condition.
But what if I want to know if there is any three items in row that incremental values(plus 1): here they are {4, 5, 6}.
Patrick already answered your question with a good solution, but if you're really looking for a LINQ-only way, you could use Aggregate:
var inputs = new List<IEnumerable<int>>
{
new List<int>{ 4,5,2,6,8,4,5,6,5,6,8,9,9 },
new List<int>{ 1,2,3 },
new List<int>{ 1,2,4 },
};
foreach(var input in inputs)
{
var result = input.Aggregate(Enumerable.Empty<int>(),
(agg, cur) => agg.Count() == 3 ? agg
: agg.Any() && cur == agg.Last() + 1
? agg.Concat(new []{cur})
: new []{cur});
Console.WriteLine(result.Count() >= 3 ? String.Join(", ", result) : "not found");
}
Another way is to take all of the groups of 3 and then see which group(s) meet your n, n+1 and n+2 rule
var results = Enumerable.Range(0, ints.Count - 3)
.Select(n => ints.Skip(n).Take(3).ToArray())
.Where(three => three[0]+1 == three[1] && three[0]+2 == three[2])
.ToArray();
I would drop the LINQ requirement. It is very hard, maybe even impossible. A regular foreach statement is better suited for this:
List<int> sequence = new List<int>();
List<int> longestSequence = null;
int previous = 0;
foreach (int i in ints)
{
if (i != previous + 1 && sequence.Count > 0)
{
if (longestSequence == null || longestSequence.Count < sequence.Count)
{
longestSequence = sequence;
}
sequence = new List<int>();
}
sequence.Add(i);
previous = i;
}

Best sequence using LINQ

I have ordered list like in example
var someList = new List<int>{1,1,2,3,5,2,1,3,7,1};
I want to select by using LINQ best(highest sum) sequence of 3 numbers.
In this case answer is 3,7,1 or 1,3,7. Is that possible without change order or sorting?
I have an idea how to do this without LINQ, but I just wanna know to do with LINQ
You can use Skip/Zip to end up with triples. For example:
var triples = list.Zip(list.Skip(1).Zip(list.Skip(2), (b, c) => new { b, c }),
(a, bc) => new { a, bc.b, bc.c });
(That may have some errors - I haven't tested it yet.)
You can then order those triples pretty easily:
var orderedTriples = triples.OrderByDescending(t => t.a + t.b + t.c);
If you're using the triples in multiple contexts, you might want to write an extension method to use Tuple<,,> instead:
public static IEnumerable<Tuple<T, T, T>> InTriples<T>(this IEnumerable<T> source)
{
// Or potentially write custom code to do this. It wouldn't be too hard...
return source.Zip(list.Skip(1).Zip(list.Skip(2), (b, c) => new { b, c }),
(a, bc) => Tuple.Create(a, bc.b, bc.c));
}
As for whether LINQ is suitable for this - having the InTriples method generally available means that the rest of the code becomes pretty simple. Using Skip/Zip isn't going to be terribly efficient, but once you've got the code going using that, you can easily rewrite the InTriples method to use an iteerator block instead.
Alternative solution with summing into list directly, without creating triples:
var bestIndex = someList.Zip(someList.Skip(1), (a, b) => a + b)
.Zip(someList.Skip(2), (a, b) => a + b)
.Select((v, i) => new
{
Value = v,
Index = i
})
.OrderByDescending(x => x.Value )
.First()
.Index;
seems to return first highest sequence
using System;
using System.Collections.Generic;
using System.Linq;
namespace take3highestsum
{
class Program
{
static void Main(string[] args)
{
//question sequence
List<int> intlist = new List<int> { 1, 1, 2, 3, 5, 2, 1, 3, 7, 1 };
//display in console stuff not part of answer
foreach (int a in intlist)
{
Console.Write(a + " ");
}
Console.WriteLine();
//begin answer
//check for legit list since we need at least 3 elements
if (intlist.Count < 3) { throw new Exception("List must have more than 3 elements"); }
//stuff we will need
int lastindx = intlist.Count - 1, baseindex = -1;
//begin LINQ
int[] result = intlist.Select(a =>
{
baseindex++;//increment
//return each sequence of three numbers
return new int[]{
intlist[baseindex],//always base index
baseindex + 1 > lastindx ? 0 : intlist[baseindex + 1], //base index + 1 or 0 if out of bounds
baseindex + 2 > lastindx ? 0 : intlist[baseindex + 2] };//base index + 2 or 0 if out of bounds
}).OrderByDescending(b => b.Sum()).First();
//end LINQ
//end answer
//stuff to display proof
foreach (int a in result)
{
Console.Write(a);
}
Console.ReadLine();
}
}
}

Select indexes of all elements in sequence

Using LINQ, can I write a statement that will return an IEnumerable of the indexes of items.
Very simple instance:
{1,2,4,5,3}
would just return
{0,1,2,3,4}
and
{1,2,4,5,3}.Where(num => num == 4)
would return
{2}
It isn't exact code, but it should get the idea across.
var a = new[] {1, 2, 4, 5, 3};
//** First, generates a simple sequence with {0,1,2,3,4}
//** using the 2 parameter lambda select
var sequence1 = a.Select((_, index) => index);
//** Second, gets an array with all indexes where the value is 4.
// We need both value and index for the next line to work.
var sequence2 = a.Select((value, index) => new {value, index});
// Get all indexes where the value is 4
var indexArray = sequence2.Where(x => x.value == 4)
.Select(x => x.index).ToArray();
var numbers = Enumerable.Range(1,10).ToList();
int index = -1;
var indices = numbers.Select(x => i++).ToList();
If you're willing to change up your syntax a bit and use an extension method, the following will work. I'm not keen on it as it creates a new sequence for every call.
var sequence = new[] { 1, 2, 4, 5, 3 };
sequence.Indexer().Select(num => num.Item1); // returns {0,1,2,3,4}
sequence.Indexer().Where(num => num.Item2 == 4).Select(num => num.Item1); // returns {2}
private static IEnumerable<Tuple<int, T>> Indexer<T>(this IEnumerable<T> sequence)
{
return sequence.Select((x, y) => new Tuple<int, T>(y, x));
}
A better way would be to change up the way you're writing it altogether:
var sequence = new[] { 1, 2, 4, 5, 3 };
sequence.Select((num, index) => new { Num = num, Index = index }).Select(num => num.Index); // returns {0, 1,2,3,4}
sequence.Select((num, index) => new { Num = num, Index = index }).Where(num => num.Num == 4).Select(num => num.Index); // returns {2}
The full set of indices just depends on the number of items, not on the values, so you can do this:
IEnumerable<int> indices = Enumerable.Range(0, 5);
If you're dealing with an IEnumerable<T>, you could do the following to get the index of the item matching 4:
IEnumerable<int> values = new[] { 1, 2, 3, 4, 5 };
int indexOf4 = (
values.Select((v, i) => new {v, i})
.FirstOrDefault(vi => vi.v == 4) ?? new {v = 0, i = -1}).i;
This copes with the case where the value source doesn't contain a match (returning -1).
Of course, if you don't mind converting your IEnumerable<T> to a list then you can just call IndexOf:
int indexOf4a = values.ToList().IndexOf(4);
But, I suspect what the question is really looking for is a way to find all the indices for values that match a particular predicate. For example:
IEnumerable<int> big = values.Select((v, i) => new {v, i})
.Where(vi => vi.v > 3)
.Select (vi => vi.i);
which returns the indices of the values > 3: [3, 4].
If the predicate doesn't match any values then you'll get an empty enumerable as the result.
IEnumerable<int> seq = new[] { 1, 2, 4, 5, 3 };
// The indexes of all elements.
var indexes = Enumerable.Range(0, seq.Count());
// The index of the left-most element with value 4.
// NOTE: Will return seq.Count() if the element doesn't exist.
var index = seq.TakeWhile(x => x != 4).Count();
// The indexes of all the elements with value 4.
// NOTE: Be careful to enumerate only once.
int current_index = 0;
var all_indexes =
from e in (
from x in seq
select new { x, Index = current_index++ }
)
where e.x == 4
select e.Index;
You can do it like this:
public static IEnumerable<int> WhereIndices<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
return source.Select(Tuple.Create<T, int>)
.Where(z => predicate(z.Item1)).Select(z => z.Item2);
}
It's an extension method, so put it in a static non-nested class. Use it just like you use Where, that is:
.WhereIndices(num => num == 4)
This should do it. Not sure how efficient it is though..
List<int> list = new List<int>()
{
1,
2,
3,
4,
5
};
var indexes = list.Select(item => list.IndexOf(item));
var index = list.Where(item => item == 4).Select(item => list.IndexOf(item));

Linq - Get the Index of the Last Non-Zero Number of Array

Is there a Linq expression that returns the index of the last non-zero value in an array? I'm not interested in an extension, only a simple linq expression.
I'm imagining something like this pseudo code:
int index = {0, 2, 1}.LastOrDefaultAt(i => i > 0);
The returned value should be 2;
You can use the Array.FindLastIndex<T> method for this:
int index = Array.FindLastIndex(myIntArray, item => item > 0);
I notice that you mention "non-zero" rather than "greater than zero" in your question text. Should your predicate be: item => item != 0 ?
List<T> has an extension method for this called FindLastIndex
var index = new int[] { 0, 2, 1}.ToList().FindLastIndex(x => x > 0);
class Program
{
static void Main(string[] args)
{
int[] index = { 0, 2, 1 };
var query = from p in index
where p != 0
orderby p descending
select p;
Console.WriteLine(query.FirstOrDefault());
Console.ReadKey();
}
}
Output: 2. Could be written in method syntax if desired:
var index = new int[] { 0, 2, 1 }.Where(a => a != 0).OrderByDescending(a => a).FirstOrDefault();

LINQ to count Continues repeated items(int) in an int Array?

Here is an scenario of my question: I have an array, say:
{ 4, 1, 1, 3, 3, 2, 5, 3, 2, 2 }
The result should be something like this (array element => its count):
4 => 1
1 => 2
3 => 2
2 => 1
5 => 1
3 => 1
2 => 2
I know this can be achieved by for loop.
But google'd a lot to make this possible using lesser lines of code using LINQ without success.
I believe the most optimal way to do this is to create a "LINQ-like" extension methods using an iterator block. This allows you to perform the calculation doing a single pass over your data. Note that performance isn't important at all if you just want to perform the calculation on a small array of numbers. Of course this is really your for loop in disguise.
static class Extensions {
public static IEnumerable<Tuple<T, Int32>> ToRunLengths<T>(this IEnumerable<T> source) {
using (var enumerator = source.GetEnumerator()) {
// Empty input leads to empty output.
if (!enumerator.MoveNext())
yield break;
// Retrieve first item of the sequence.
var currentValue = enumerator.Current;
var runLength = 1;
// Iterate the remaining items in the sequence.
while (enumerator.MoveNext()) {
var value = enumerator.Current;
if (!Equals(value, currentValue)) {
// A new run is starting. Return the previous run.
yield return Tuple.Create(currentValue, runLength);
currentValue = value;
runLength = 0;
}
runLength += 1;
}
// Return the last run.
yield return Tuple.Create(currentValue, runLength);
}
}
}
Note that the extension method is generic and you can use it on any type. Values are compared for equality using Object.Equals. However, if you want to you could pass an IEqualityComparer<T> to allow for customization of how values are compared.
You can use the method like this:
var numbers = new[] { 4, 1, 1, 3, 3, 2, 5, 3, 2, 2 };
var runLengths = numbers.ToRunLengths();
For you input data the result will be these tuples:
4 1
1 2
3 2
2 1
5 1
3 1
2 2
(Adding another answer to avoid the two upvotes for my deleted one counting towards this...)
I've had a little think about this (now I've understood the question) and it's really not clear how you'd do this nicely in LINQ. There are definitely ways that it could be done, potentially using Zip or Aggregate, but they'd be relatively unclear. Using foreach is pretty simple:
// Simplest way of building an empty list of an anonymous type...
var results = new[] { new { Value = 0, Count = 0 } }.Take(0).ToList();
// TODO: Handle empty arrays
int currentValue = array[0];
int currentCount = 1;
foreach (var value in array.Skip(1))
{
if (currentValue != value)
{
results.Add(new { Value = currentValue, Count = currentCount });
currentCount = 0;
currentValue = value;
}
currentCount++;
}
// Handle tail, which we won't have emitted yet
results.Add(new { Value = currentValue, Count = currentCount });
Here's a LINQ expression that works (edit: tightened up code just a little more):
var data = new int[] { 4, 1, 1, 3, 3, 2, 5, 3, 2, 2 };
var result = data.Select ((item, index) =>
new
{
Key = item,
Count = (index == 0 || data.ElementAt(index - 1) != item)
? data.Skip(index).TakeWhile (d => d == item).Count ()
: -1
}
)
.Where (d => d.Count != -1);
And here's a proof that shows it working.
This not short enough?
public static IEnumerable<KeyValuePair<T, int>> Repeats<T>(
this IEnumerable<T> source)
{
int count = 0;
T lastItem = source.First();
foreach (var item in source)
{
if (Equals(item, lastItem))
{
count++;
}
else
{
yield return new KeyValuePair<T, int>(lastItem, count);
lastItem = item;
count = 1;
}
}
yield return new KeyValuePair<T, int>(lastItem, count);
}
I'll be interested to see a linq way.
I already wrote the method you need over there. Here's how to call it.
foreach(var g in numbers.GroupContiguous(i => i))
{
Console.WriteLine("{0} => {1}", g.Key, g.Count);
}
Behold (you can run this directly in LINQPad -- rle is where the magic happens):
var xs = new[] { 4, 1, 1, 3, 3, 2, 5, 3, 2, 2 };
var rle = Enumerable.Range(0, xs.Length)
.Where(i => i == 0 || xs[i - 1] != xs[i])
.Select(i => new { Key = xs[i], Count = xs.Skip(i).TakeWhile(x => x == xs[i]).Count() });
Console.WriteLine(rle);
Of course, this is O(n^2), but you didn't request linear efficiency in the spec.
var array = new int[] {1,1,2,3,5,6,6 };
foreach (var g in array.GroupBy(i => i))
{
Console.WriteLine("{0} => {1}", g.Key, g.Count());
}
var array = new int[]{};//whatever ur array is
array.select((s)=>{return array.where((s2)=>{s == s2}).count();});
the only prob with is tht if you have 1 - two times you will get the result for 1-two times
var array = new int[] {1,1,2,3,5,6,6 };
var arrayd = array.Distinct();
var arrayl= arrayd.Select(s => { return array.Where(s2 => s2 == s).Count(); }).ToArray();
Output
arrayl=[0]2 [1]1 [2]1 [3]1 [4]2
Try GroupBy through List<int>
List<int> list = new List<int>() { 4, 1, 1, 3, 3, 2, 5, 3, 2, 2 };
var res = list.GroupBy(val => val);
foreach (var v in res)
{
MessageBox.Show(v.Key.ToString() + "=>" + v.Count().ToString());
}

Categories

Resources