C# using LINQ to limit a recursive list - c#

I'm trying to figure out how to use LINQ to limit a recursive call.
My intention with the following code is to run through a list of numbers (num) and for each number recursively count/print up to a set amount (6).
the sequence in newnum that I'm trying to get is : 3 4
5
1
2
3
4
5
5
2
3
4
5
but naturally I'm running into an infinite loop instead. The .Where predicate isn't stopping the loop as I had thought and it's probable my base case is off. Any insight as to the proper way to set this up? Thank you.
var num = new[] {3, 1, 8, 5, 2};
Func<int, int> writeString = delegate(int count)
{
Func<int, int> recursiveWrite = null;
recursiveWrite = n =>
{
Console.WriteLine("string " + n);
recursiveWrite(n+1);
return n;
};
return recursiveWrite(count);
};
var newnum = num.Where(n => writeString(n) < 6); // is this possible?
newnum.ToList().ForEach( w => Console.WriteLine(w));
I noticed that a similar stopping pattern occurs in the following sample code, the .Where will only include factorials less than 7, what am I missing?
var numbers = new[] { 5,1,3,7,2,6,4};
Func<int, int> factorial = delegate(int num) {
Func<int, int> locFactorial = null;
locFactorial = n => n == 1 ? 1 : n * locFactorial(n - 1);
return locFactorial(num);
};
var smallnums = numbers.Where(n => factorial(n) < 7);

The answer is that you don't have a base case. Once your recursive function is executed, there is nothing to stop it - LINQ doesn't perform any kind of magic that can modify the internal logic of another function.
In the example you are missing this key bit of code that will stop the recursion - the base case:
locFactorial = n => n == 1 ? 1 : n * locFactorial(n - 1);
The ternary operator checks to see if n==1 - if it is, it returns 1. This is the base case that your function lacks.
There is no way to provide a base-case to your function through LINQ alone. You need to build this into the recursive function.
Additionally, you are returning the wrong type from your recursive function if you want to return a list of numbers from a single number: this is fundamentally a different case from the Factorial function which returns a single number given a single number.
Here is a function that does what you require without using recursion:
void Main()
{
var numbers = new[] {3, 1, 8, 5, 2};
numbers.SelectMany(x => GetIncreasing(x).TakeWhile(y => y < 6));
}
IEnumerable<int> GetIncreasing(int x)
{
while (true)
yield return x++;
}

You could just stick with generating sequences that fits your requirements, something like:
var num = new[] { 3, 1, 8, 5, 2 };
var limit = 6;
var query = from n in num
where n < limit // sanity check
from pn in Enumerable.Range(n, limit - n)
select pn;
Decent performance and clean code

The difference with the factorial sample is the placing of the end condition. This is what you should do:
recursiveWrite = n =>
{
Console.WriteLine("string " + n);
if (n < 6)
recursiveWrite(n+1);
return n;
};

Not completely sure of what you are trying to achieve but I hope this willl help.
You need a stop condition in your recursive lambda (as n==1 in factorial).
With nested funcs, you can inject this limit "dynamically".
class Program
{
static void Main(string[] args)
{
var num = new[] { 3, 1, 8, 5, 2 };
Func<int, Func<int, IEnumerable<int>>> writeString =
delegate(int maxcount)
{
Func<int, IEnumerable<int>> recursiveWrite = null;
recursiveWrite = (n) =>
{
if (n < maxcount)
{
Console.WriteLine("string " + n);
var rec = recursiveWrite(n + 1);
return new List<int>(){n}.Concat(rec);
}
return new List<int>();
};
return recursiveWrite;
};
var newnum = num.SelectMany(n => writeString(6)(n)); // is this possible?
newnum.ToList().ForEach(w => Console.WriteLine(w));
Console.ReadLine();
}
}

Related

Determine lower value from a list using LINQ in C#

I have a list with four double values in it
var numbers2 = new List<double>() { 2, 3, 9, 7 };
I need to get lower value between the first 2 indexes (2 and 3).
Similarly I need to get lower value between index 3 and 4 (9 and 7)
Is there a way in C sharp to determine this using LINQ?
Once I have the lower value from above list i.e 2 and 7; I need to pass these values in the below loop
for (int i = 0; i < 1; i++)
{
dac[i] = SetValue(lowerValue[j]);
}
if i == 0, I want lowerValue[j] = 2. If i == 1, I want lowerValue[j] = 7
Well as others have pointed out, it doesn't seem like there's any reason to use linq. But if you absolutely had to find some way to do it, then it's possible. I'll throw 3 options out, the last one being linq.
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var numbers2 = new List<double>() { 2, 3, 9, 7 };
// you stated it's always 4 values. There's no reason to use linq. The optimal solution would
// be a variation of this (with some constant values instead of magic numbers)..
var first = Math.Min(numbers2[0],numbers2[1]);
var second = Math.Min(numbers2[2],numbers2[3]);
Console.WriteLine($"Lower values: {first},{second}");
// if it was an arbitry sized list (but always even count) you could use a iterator method
var listOfLowerValues = ToPairs(numbers2);
var values = string.Join(",", listOfLowerValues.Select(x => x.ToString()));
Console.WriteLine($"Lower values: {values}");
// finally if you absolutely had too, you can make it even more inefficient
// by using linq.
var indexes = Enumerable.Range(0, numbers2.Count);
var indexed = numbers2.Zip(indexes, (n,i) => (index: i, num: n));
var odd = indexed.Where(x => x.index%2 == 0).Select(x => x.num).ToArray();
var even = indexed.Where(x => x.index%2 > 0).Select(x => x.num).ToArray();
var lower = even.Zip(odd,(v1,v2)=> v1 < v2 ? v1 : v2);
var valuesByLinq = string.Join(",",lower.Select(x => x.ToString()));
Console.WriteLine($"Lower values: {valuesByLinq}");
}
static IEnumerable<double> ToPairs(IEnumerable<double> source)
{
int index = 0;
double previous = 0;
foreach(var n in source)
{
if(index++%2 > 0)
{
yield return (previous < n) ? previous : n;
}
else
{
previous = n;
}
}
}
}

How to count how many times exist each number from int[] inside IEnumerable<int>?

I have array of ints(Call him A) and IEnumarable(Call him B):
B - 1,2,4,8,289
A - 2,2,56,2,4,33,4,1,8,
I need to count how many times exist each number from A inside B and sum the result.
For example:
B - 1,2,4,8,289
A - 2,2,56,2,4,33,4,1,8,
result = 1+3+2+1+0
What is elegant way to implement it?
With LINQ it is easy:
int count = A
.Where(x => B.Contains(x))
.Count();
Counts how many times elements from A are contained in B.
As Yuval Itzchakov points out, this can be simplified like this:
int count = A.Count(x => B.Contains(x));
I need to count how many times exist each number from A inside B and sum the result.
You can get both the count and sum as follows
List<int> b = new List<int>() { 1,2,4,8,289 };
List<int> a = new List<int>() { 2,2,56,2,4,33,4,1,8 };
var subset = a.Where(i => b.Contains(i));
var count = subset.Count(); // 7
var sum = subset.Sum(); // 23
Note that I reuse the same Linq expression to get both the count and the sum.
One might be tempted to use a HashSet<int> in place of a List<int> because the .Contains operation is faster. However, HashSet is a set, meaning if the same number is added multiple times, only one copy of that number will remain in the set.
sweet and simple.. one line solution
why dont you try it..
int sum = 0;
A.ToList().ForEach(a=>sum +=B.Count(b=>b==a));
Console.Write(sum);
you can sweap the A/B it will still work
With Linq you can do like this
var B = new List<int>{ 1, 2, 4, 8, 289 };
var A = new List<int> { 2, 2, 56, 2, 4, 33, 4, 1, 8 };
var repetitionSum = B.Select(b => A.Count(a => a == b)).Sum(); //result = 7
And if you want, you can get the individual repetition list like this
var repetition = B.Select(b => A.Count(a => a == b)).ToList();
// { 1, 3, 2, 1, 0 }
It is not clear if you want to know the occurrences of each number or the final count (your text and your example code differ). Here is the code to get the number of appearances of each number
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
int[] a = new []{1,2,3};
int[] b = new []{1,2,2,3};
Dictionary<int, int> aDictionary = a.ToDictionary(i=>i, i => 0);
foreach(int i in b)
{
if(aDictionary.ContainsKey(i))
{
aDictionary[i]++;
}
}
foreach(KeyValuePair<int, int> kvp in aDictionary)
{
Console.WriteLine(kvp.Key + ":" + kvp.Value);
}
}
}

How to read this lambda expression

Can someone read me the following line lambda.
n => n % 2 == 1
Also if I have to write the same piece of code without lambda how would I write it. It might make me understand.
Another piece of code is below
List<int> numbers = new List<int>{11,37,52};
List<int> oddNumbers = numbers.where(n => n % 2 == 1).ToList();
Reading the expression out loud would be
n 'goes to' n modulus two equals one
n => n % 2 == 1
Essentially, you can think of this lambda as a function that returns true when the value provided to it (n) is odd and positive, false otherwise. You could also write this as a method
bool IsOddAndPositive(int n)
{
return n % 2 == 1;
}
Using it as in your snippet would be
List<int> numbers = new List<int>{11, 37, 52};
List<int> oddNumbers = numbers.Where(IsOddAndPositive).ToList();
And the result (of both what you've specified and the method example) is
11, 37
this function
n => n % 2 == 1
takes one argument (n) and return boolean value:
true, if n is odd: n % 2 == 1 (n is odd if and only if it has remainder 1 when divided by 2)
false otherwise (if n is even)
When re-written as ordinary function it would be equivalent to
Boolean IsOdd(int n) { -- <- I've named it "IsOdd" since lambda functions have no explict names while ordinary functions have
return n % 2 == 1;
}
Your code below
List<int> oddNumbers = numbers.where(n => n % 2 == 1).ToList();
i's a LINQ expression which selects odd values from the list
As for youer problem, how you would write it without lambda:
int[] digits = {1,2,3,4,5,6,7,8,9,10};
int[] OddDigits = new int[5];
for(int i = 0; i < digits.Length; i++)
{
if(digits[i] % 2 == 1)
{
int x = 0;
OddDigits[x] = digits[i];
x++;
}
}
I just replaced the list with arrays for simplicity. As I stated in my comment earlier, it is a simple modulo operation
Line 1 instantiates a list of 3 integers
The % operator, also called modulo operator, computes the remainder after dividing its first operand by its second
The results of the second line will be a list containing 11 and 37.
you could write this like this using a foreach:
List<int> numbers = new List<int> { 11, 37, 52 };
List<int> oddNumbers = new List<int>();
foreach (var num in numbers)
{
if (num % 2 == 1)
{
oddNumbers.Add(num);
}
}
you could also use Array.ForEach, like this:
numbers.ForEach(num =>
{
if (num % 2 == 1)
oddNumbers.Add(num);
});

Lists permutations (unknown number) [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Combination of List<List<int>>
I have multiple Lists, could be 2 or 3 up to 10 lists, with multiple
values in them. Now what I need to do is to get a combination of all
of them.
For example, if I have 3 lists with the following values:
List 1: 3, 5, 7
List 2: 3, 5, 6
List 3: 2, 9
I would get these combinations
3,3,2
3,3,9
3,5,2
Etc..
Now the problem is I cannot do this easily because I do not know how many lists I have, therefore determine how many loops I need.
You could probably make that a lot easier, but this is what I had in mind just now:
List<List<int>> lists = new List<List<int>>();
lists.Add(new List<int>(new int[] { 3, 5, 7 }));
lists.Add(new List<int>(new int[] { 3, 5, 6 }));
lists.Add(new List<int>(new int[] { 2, 9 }));
int listCount = lists.Count;
List<int> indexes = new List<int>();
for (int i = 0; i < listCount; i++)
indexes.Add(0);
while (true)
{
// construct values
int[] values = new int[listCount];
for (int i = 0; i < listCount; i++)
values[i] = lists[i][indexes[i]];
Console.WriteLine(string.Join(" ", values));
// increment indexes
int incrementIndex = listCount - 1;
while (incrementIndex >= 0 && ++indexes[incrementIndex] >= lists[incrementIndex].Count)
{
indexes[incrementIndex] = 0;
incrementIndex--;
}
// break condition
if (incrementIndex < 0)
break;
}
If I’m not completely wrong, this should be O(Nm) with m being the number of lists and N the number of permutations (product of the lengths of all m lists).
you could make a List<List<yourValueType> mainlist in which you put all your lists.
then with a simple
int numberOfIterations = 1;
foreach(var item in mainlist)
{
numberOfIterations *= item.Count;
}
this would get the amount of iterations you would have to execute in total.
Non-recursive solution, works on any IEnumerables (not just lists) without solidifying them:
public static IEnumerable<IEnumerable<T>> Permutations<T>(
this IEnumerable<IEnumerable<T>> source)
{
// Check source non-null, non-empty?
var enumerables = source.ToArray();
Stack<IEnumerator<T>> fe = new Stack<IEnumerator<T>>();
fe.Push(enumerables[0].GetEnumerator());
while (fe.Count > 0)
{
if (fe.Peek().MoveNext())
{
if (fe.Count == enumerables.Length)
yield return new Stack<T>(fe.Select(e => e.Current));
else
fe.Push(enumerables[fe.Count].GetEnumerator());
}
else
{
fe.Pop().Dispose();
}
}
}
Not very efficient but very easy to understand approach might be to solve this task recursively. Consider a method which computes permutations for N lists. If you have such a method then you can easily compute permutations for N+1 lists by combining all permutation of N lists with every number in the last list. You should also handle corner case which permutations of 0 lists. Then implementation seems to be straightforward:
IEnumerable<IEnumerable<T>> GetAllPermutations<T>(IEnumerable<IEnumerable<T>> inputLists)
{
if (!inputLists.Any()) return new [] { Enumerable.Empty<T>() };
else
{
foreach (var perm in GetAllPermutations(inputLists.Skip(1)))
foreach (var x in inputLists.First())
yield return new[]{x}.Concat(perm);
}
}
As an alternative, following rawlings general idea the following should work
public static IEnumerable<IEnumerable<T>> Permutations<T> (this IEnumerable<IEnumerable<T>> underlying)
{
var enumerators = new Queue<IEnumerator<T>>(underlying.Select(u => u.GetEnumerator())
.Where(enumerator => enumerator.MoveNext());
Boolean streaming = enumerators.Any();
if(streaming)
{
IEnumerable<T> result;
IEnumerator<T> finalEnumerator = enumerators.Dequeue();
Func<Boolean,Boolean> finalAction = b => b ? b : finalEnumerator.MoveNext();
Func<Boolean,Boolean> interimAction =
enumerators.Reverse()
.Select(enumerator => new Func<Boolean,Boolean>(b => b ? b : (enumerator.MoveNext() ? true : enumerator.ResetMove())))
.Aggregate((f1,f2) => (b => f1(f2(b)));
enumerators.Enqueue(finalEnumerator);
Func<Boolean,Boolean> permutationAction =
interimAction == null ?
finalAction :
b => finalAction(interimAction(b));
while(streaming)
{
result = new Queue<T>(enumerators.Select(enumerator => enumerator.Current))
streaming = permutationAction(true);
yield return result;
}
}
private static Boolean ResetMove<T>(this IEnumerator<T> underlying)
{
underlying.Reset();
underlying.MoveNext();
return false;
}

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