Convert Lambda expression in OrderBy Predicate from C# to VB.net - c#

I've got the following to sort entities by their job position. The desired order ist defined in another array. In C# this code works:
IEnumerable<CreditObject> query = credits.OrderBy(x =>
{
for (int i = 0; i < list.Length; i++)
{
if (x.Job == list[i])
return i;
}
throw new NotImplementedException("Job not within List");
});
However I will have to convert this to VB.net. I read the equivalent would be something like the following:
Dim query As IEnumerable(Of CreditObject) = credits.OrderBy(Function(x)
For j As Integer = 0 To templ.Length - 1
If x.Job = templ(j) Then
Return j
End If
Next
End Function)
This does not compile, gives me "Expression expected" right after the Function(x). What am I doing wrong?

First, you make that into a bonafide method:
public int GetCreditObjectPosition(CreditObject x, List<int> list) {
for (int i = 0; i < list.Length; i++) {
if (x.Job == list[i]) {
return i;
}
}
throw new NotImplementedException("Job not within List");
}
Then, you just say:
IEnumerable<CreditObject> query =
credits.OrderBy(x => GetCreditObjectPosition(x, list));
That's easy enough to convert to VB.
Next, you rewrite GetCreditObjectPosition for massive performance improvements:
public int GetCreditObjectPosition(CreditObject x, List<int> list) {
var jobDictionary =
list.Select((job, index) => new { Job = job, Index = Index } )
.ToDictionary(item => item.Job, item => item.Index);
int position;
if(!jobDictionary.TryGetValue(x.Job, out position)) {
throw new Exception("Job not within List");
}
return position;
}

Related

Why does this fail when I don't use the ToList method in a for loop?

I am wondering why if I change the line
"sub = sub.SelectMany(x => x.Next(i)).ToList();"
to
"sub = sub.SelectMany(x => x.Next(i));"
I get the error
Line 48: System.IndexOutOfRangeException: Index was outside the bounds of the array" when I provide an input of 4 to the method SolveNQueens.
I believe it may have something to do with lazy evaluation.
The full code sample is listed below and is a valid solution
to the n queens problem.
public class Solution {
public IList<IList<string>> SolveNQueens(int n)
{
IEnumerable<PartialQueens> sub = new List<PartialQueens>(){
new PartialQueens(n)};
for(int i=0;i<n;i++)
{
sub = sub.SelectMany(x => x.Next(i)).ToList();
}
return sub.Select(x => x.ToPosition()).ToList();
}
}
public class PartialQueens
{
public byte FREE = 0;
public byte BLOCKED = 1;
public byte QUEEN = 2;
public byte[,] fill;
int n;
public PartialQueens(int n)
{
this.n = n;
fill = new byte[n,n];
}
public PartialQueens(byte[,] fill, int n)
{
this.fill = fill;
this.n = n;
}
public PartialQueens Fill(int row, int column)
{
byte[,] newFill = fill.Clone() as byte[,];
newFill[row,column] = QUEEN;
Action<int,int> f = (x,y) =>
{
if(y >= 0 && y < n)
newFill[x,y] = BLOCKED;
};
for(int i=1;i<n-row;i++)
{
f(row+i,column+i);
f(row+i,column-i);
f(row+i,column);
}
return new PartialQueens(newFill,n);
}
public IEnumerable<PartialQueens> Next(int row)
{
for(int j=0;j<n;j++)
{
if(fill[row,j] == FREE)
yield return Fill(row,j);
}
}
public IList<string> ToPosition()
{
return Enumerable.Range(0,n).Select(i => ConvertRow(i)).ToList();
}
public string ConvertRow(int i)
{
StringBuilder builder = new StringBuilder();
for(int j=0;j<n;j++)
{
if(fill[i,j] == QUEEN)
builder.Append("Q");
else
builder.Append(".");
}
return builder.ToString();
}
}
The reason this fails is because of the way that the iterator variable used in a for loop is evaluated when it is captured by a closure. When you remove the ToList() inside the loop, the sub IEnumerable is only evaluated when sub is materialized in the return statement return sub.Select(x => x.ToPosition()).ToList();. At this time, the for loop variable i will have a value of n (e.g. 8 on a standard chess board), which is outside the array bounds.
However, when you materialize the List immediately, the side effect isn't encountered, since the value of i is used before the next iteration (ToList materializes).
Works:
for (int i = 0; i < n; i++)
{
// Materialized here so `i` evaluated immediately
sub = sub.SelectMany(x => x.Next(i)).ToList();
}
Broken:
for (int i = 0; i < n; i++)
{
sub = sub.SelectMany(x => x.Next(i));
}
return sub.Select(x => x.ToPosition()).ToList(); // `i` evaluated here
To fix the for loop variable evaluation issue, you can explicitly capture the current value of the iterator variable:
for (int i = 0; i < n; i++)
{
var loop = i;
sub = sub.SelectMany(x => x.Next(loop)); // No To List - lazy evaluation
}
Re : Avoiding for loops in FP Paradigm code
OP's SolveNQueens method uses a loop which progressively changes the sub, rather than recursion, but the for can also be replaced with a foreach and a range:
foreach(var i in Enumerable.Range(0, n))
{
sub = sub.SelectMany(x => x.Next(i));
}
Which Resharper then offers to re-write as a left fold:
sub = Enumerable.Range(0, n)
.Aggregate(sub, (current, i) => current.SelectMany(x => x.Next(i)));
Either way, the flaw in lazy evaluation of the iterator variable inside a for loop is avoided.

Yield return from an indexed iteration via LINQ

Leaving the performance cost of LINQ usage, I would like to know how to convert the following code into a LINQ expression
for (int i = 0; i < someArray.length(); i++)
yield return new SomeEntity(someFunction(i));
Important: I need the use of the incremented index
Update:
Rather than someArray.length(), number should be used:
for (int i = 0; i < number; i++)
yield return new SomeEntity(someFunction(i));
2nd update
I'm still getting the compilation error "not all code paths return value"
My code:
public static IEnumerable function()
{
Enumerable.Range(0,5).Select(i => new Entity());
}
3rd update
Didn't think it's relevant until I found out it's the cause for this error..
public static IEnumerable function()
{
int[] arr = { 1, 2, 3, 4 };
foreach (int i in arr)
{
Enumerable.Range(0,5).Select(i => new Entity());
}
}
If you take out the foreach 1st loop out of the equation, all replies answer to this question, but my issue is n^2.. 2 nested loops...
Any ideas?
Use the overload of Enumerable.Select that has an index into the collection:
someArray.Select((x, i) => new SomeEntity(someFunction(i)));
Edit
As you've modified your example and are not actually using a collection to iterate and index to, use Enumerable.Range:
Enumerable.Range(0, number).Select(i => new SomeEntity(someFunction(i)));
Use Enumerable.Range to generate the numbers:
Enumerable.Range(0,number).Select(i=>new SomeEntity(someFunction(i)));
Here's my LinqPad snippet.
void Main()
{
var e = SomeEntity.GetEntities(new List<int> { 1, 2, 3});
e.Dump();
}
public class SomeEntity
{
public int m_i;
public SomeEntity(int i)
{
m_i = i;
}
public override string ToString()
{
return m_i.ToString();
}
public static int someFunction(int i){ return i+100;}
public static IEnumerable<SomeEntity> GetEntities(IEnumerable<int> someArray)
{
// for (int i = 0; i < someArray.Count();i++)
// yield return new SomeEntity(someFunction(i));
// *** Equivalent linq function ***
return someArray.Select(a => new SomeEntity(someFunction(a)));
}
}

How to iterate lists with different lengths to find all permutations?

This one should not be too hard but my mind seems to be having a stack overflow (huehue). I have a series of Lists and I want to find all permutations they can be ordered in. All of the lists have different lengths.
For example:
List 1: 1
List 2: 1, 2
All permutations would be:
1, 1
1, 2
In my case I don't switch the numbers around. (For example 2, 1)
What is the easiest way to write this?
I can't say if the following is the easiest way, but IMO it's the most efficient way. It's basically a generalized version of the my answer to the Looking at each combination in jagged array:
public static class Algorithms
{
public static IEnumerable<T[]> GenerateCombinations<T>(this IReadOnlyList<IReadOnlyList<T>> input)
{
var result = new T[input.Count];
var indices = new int[input.Count];
for (int pos = 0, index = 0; ;)
{
for (; pos < result.Length; pos++, index = 0)
{
indices[pos] = index;
result[pos] = input[pos][index];
}
yield return result;
do
{
if (pos == 0) yield break;
index = indices[--pos] + 1;
}
while (index >= input[pos].Count);
}
}
}
You can see the explanation in the linked answer (shortly it's emulating nested loops). Also since for performace reasons it yields the internal buffer w/o cloning it, you need to clone it if you want store the result for later processing.
Sample usage:
var list1 = new List<int> { 1 };
var list2 = new List<int> { 1, 2 };
var lists = new[] { list1, list2 };
// Non caching usage
foreach (var combination in lists.GenerateCombinations())
{
// do something with the combination
}
// Caching usage
var combinations = lists.GenerateCombinations().Select(c => c.ToList()).ToList();
UPDATE: The GenerateCombinations is a standard C# iterator method, and the implementation basically emulates N nested loops (where N is the input.Count) like this (in pseudo code):
for (int i0 = 0; i0 < input[0].Count; i0++)
for (int i1 = 0; i1 < input[1].Count; i1++)
for (int i2 = 0; i2 < input[2].Count; i2++)
...
for (int iN-1 = 0; iN-1 < input[N-1].Count; iN-1++)
yield { input[0][i0], input[1][i1], input[2][i2], ..., input[N-1][iN-1] }
or showing it differently:
for (indices[0] = 0; indices[0] < input[0].Count; indices[0]++)
{
result[0] = input[0][indices[0]];
for (indices[1] = 0; indices[1] < input[1].Count; indices[1]++)
{
result[1] = input[1][indices[1]];
// ...
for (indices[N-1] = 0; indices[N-1] < input[N-1].Count; indices[N-1]++)
{
result[N-1] = input[N-1][indices[N-1]];
yield return result;
}
}
}
Nested loops:
List<int> listA = (whatever), listB = (whatever);
var answers = new List<Tuple<int,int>>;
for(int a in listA)
for(int b in listB)
answers.add(Tuple.create(a,b));
// do whatever with answers
Try this:
Func<IEnumerable<string>, IEnumerable<string>> combine = null;
combine = xs =>
xs.Skip(1).Any()
? xs.First().SelectMany(x => combine(xs.Skip(1)), (x, y) => String.Format("{0}{1}", x, y))
: xs.First().Select(x => x.ToString());
var strings = new [] { "AB", "12", "$%" };
foreach (var x in combine(strings))
{
Console.WriteLine(x);
}
That gives me:
A1$
A1%
A2$
A2%
B1$
B1%
B2$
B2%
I made the following IEnumerable<IEnumerable<TValue>> class to solve this problem which allows use of generic IEnumerable's and whose enumerator returns all permutations of the values, one from each inner list. It can be conventiently used directly in a foreach loop.
It's a variant of Michael Liu's answer to IEnumerable and Recursion using yield return
I've modified it to return lists with the permutations instead of the single values.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Permutation
{
public class ListOfListsPermuter<TValue> : IEnumerable<IEnumerable<TValue>>
{
private int count;
private IEnumerable<TValue>[] listOfLists;
public ListOfListsPermuter(IEnumerable<IEnumerable<TValue>> listOfLists_)
{
if (object.ReferenceEquals(listOfLists_, null))
{
throw new ArgumentNullException(nameof(listOfLists_));
}
listOfLists =listOfLists_.ToArray();
count = listOfLists.Count();
for (int i = 0; i < count; i++)
{
if (object.ReferenceEquals(listOfLists[i], null))
{
throw new NullReferenceException(string.Format("{0}[{1}] is null.", nameof(listOfLists_), i));
}
}
}
// A variant of Michael Liu's answer in StackOverflow
// https://stackoverflow.com/questions/2055927/ienumerable-and-recursion-using-yield-return
public IEnumerator<IEnumerable<TValue>> GetEnumerator()
{
TValue[] currentList = new TValue[count];
int level = 0;
var enumerators = new Stack<IEnumerator<TValue>>();
IEnumerator<TValue> enumerator = listOfLists[level].GetEnumerator();
try
{
while (true)
{
if (enumerator.MoveNext())
{
currentList[level] = enumerator.Current;
level++;
if (level >= count)
{
level--;
yield return currentList;
}
else
{
enumerators.Push(enumerator);
enumerator = listOfLists[level].GetEnumerator();
}
}
else
{
if (level == 0)
{
yield break;
}
else
{
enumerator.Dispose();
enumerator = enumerators.Pop();
level--;
}
}
}
}
finally
{
// Clean up in case of an exception.
enumerator?.Dispose();
while (enumerators.Count > 0)
{
enumerator = enumerators.Pop();
enumerator.Dispose();
}
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}
You can use it directly in a foreach like this:
public static void Main(string[] args)
{
var listOfLists = new List<List<string>>()
{
{ new List<string>() { "A", "B" } },
{ new List<string>() { "C", "D" } }
};
var permuter = new ListOfListsPermuter<string>(listOfLists);
foreach (IEnumerable<string> item in permuter)
{
Console.WriteLine("{ \"" + string.Join("\", \"", item) + "\" }");
}
}
The output:
{ "A", "C" }
{ "A", "D" }
{ "B", "C" }
{ "B", "D" }

Permutations using same letters

I am current working on a project where I need to generate all possible permutations from a given set of characters. I am currently using this code:
public static IEnumerable<string> AllPermutations(this IEnumerable<char> s)
{
return s.SelectMany(x =>
{
var index = Array.IndexOf(s.ToArray(), x);
return s.Where((y, i) => i != index).AllPermutations().Select(y => new string(new[] { x }.Concat(y).ToArray())).Union(new[] { new string(new[] { x }) });
}).Distinct();
}
From this answer.
The problem I have is that it won't generate permuations that use the same letter more than once.
For example if I used abcde as the input I need it to generate combinations like aaaaa and dcc etc.
I'm not experienced enough with LINQ to understand where the code is stopping duplicate letters. Any help is greatly appreciated.
This might work, but I'm sure it could be done more efficiently (taking the counting prompt from PeskyGnat):
static IEnumerable<string> GetVariations(string s)
{
int[] indexes = new int[s.Length];
StringBuilder sb = new StringBuilder();
while (IncrementIndexes(indexes, s.Length))
{
sb.Clear();
for (int i = 0; i < indexes.Length; i++)
{
if (indexes[i] != 0)
{
sb.Append(s[indexes[i]-1]);
}
}
yield return sb.ToString();
}
}
static bool IncrementIndexes(int[] indexes, int limit)
{
for (int i = 0; i < indexes.Length; i++)
{
indexes[i]++;
if (indexes[i] > limit)
{
indexes[i] = 1;
}
else
{
return true;
}
}
return false;
}
Edit: Changed to use yield return as per Rawlings suggestion. Much better memory usage if you don't need to keep all the results and you can start using the results before they've all been generated.
I'm amazed this works. It basically goes "make a list of strings from the characters. Then to each string taken from the list, add each character again, and add the resulting strings to the list. Repeat until you've got the right length."
public static IEnumerable<string> BuildStrings(this IEnumerable<char> alphabet)
{
var strings = alphabet.Select(c => c.ToString());
for (int i = 1; i < alphabet.Count(); i++)
{
strings = strings.Union(strings.SelectMany(s => alphabet.Select(c => s + c.ToString())));
}
return strings;
}
A funny one using only recursive lambdas via a fixpoint operator (thx #Rawling for the SelectMany)
// Fix point operator
public static Func<T, TResult> Fix<T, TResult>(Func<Func<T, TResult>, Func<T, TResult>> f)
{
return t => f(Fix<T, TResult>(f))(t);
}
And then
var chars = new[] {'a','b','c','d','e'}.Select(c=>c.ToString()) ;
var result = Fix<int,IEnumerable<string>>(
f =>
x =>
x == 1
? chars
: chars.Union(f(x - 1).SelectMany(s => chars.Select(c => s + c))))(chars.Count());

Using LINQ to select item in List<T> and add integer to populate new List<T>

Lets say I have List<string> = new List<string>() {"20","26","32"}
I want to create a new List based on the first number in the previous list and it should have the same number of elements in it. I will be adding a certain number to that first number and so on and so on. As an example, using 6 as the number to add I would get 20,26,32. The resulting list will be List. The number 6 is a class wide property.
The issue comes if I have a list of "N","N","32"
I need to produce the same list of 20,26,32 but I have to use the last number to work out the others.
If I had "N","26","N" I would have to use the middle number to work out the others.
The N represents no data in the input list and it will always be this character
In summary, I need to produce a new list with the same number of elements as the input list and it must take the first or next numerical element to produce the resulting list using a specified number to add/subtract values to.
I wondered if LINQ's aggregate function might be able to handle it but got a bit lost using it.
Examples:
"20","26","32" = 20,26,32
"N","26","32" = 20,26,32
"N","N","32" = 20,26,32
"20","26","N" = 20,26,32
What about something like this:
var n = 6;
List<string> strList = new List<string>() {"20","26","32"};
// list can also be {null, "26", null} , {null, "N", "32"} ,
// {"N", "26", null } etc...
var list = strList.Select(s =>
{
int v;
if(string.IsNullOrEmpty(s) || !int.TryParse(s,out v))
return (int?)null;
return v;
});
var firstValidVal = list.Select((Num, Index) => new { Num, Index })
.FirstOrDefault(x => x.Num.HasValue);
if(firstValidVal == null)
throw new Exception("No valid number found");
var bases = Enumerable.Range(0, strList.Count).Select(i => i * n);
int startVal = firstValidVal.Num.Value - bases.ElementAt(firstValidVal.Index);
var completeSequence = bases.Select(x => x + startVal);
It sounds like you want a function which will
Take a List<int> as input
Make the first element of the original list the first element of the new list
New list has same number of elements as original
Remaining numbers are the first element + a value * position
If so then try the following
static bool TryGetFirstNumber(List<string> list, out number, out index) {
for (var i = 0; i < list.Count; i++) {
var cur = list[0];
if (!String.IsNullOrEmpty(cur) && Int32.TryParse(cur, out number)) {
index = i;
return true;
}
}
number = 0;
index = 0;
return false;
}
static List<T> TheFunction(List<string> list, int increment) {
var newList = new List<int>();
int first;
int index;
if (TryGetFirstNumber(list, out first, out index)) {
first -= index * increment;
} else {
first = 0;
}
newList.Add(first);
for (var i = 1; i < list.Length; i++) {
newList.Add(first + increment);
increment += increment;
}
return newList;
}
For LINQ purposes, I sometimes resort to writing a parse method that returns an int?as the result so that I can return null when it fails to parse. Here's a complete LINQPad implementation that illustrates this and the positional select (taking an approach otherwise similar to digEmAll's):
void Main()
{
var n = 6;
var items = new List<string>
// {"20","N", "N"};
// {"N", "26", "N"};
{"N", "N", "32"};
var first = items
.Select((v,index) => new { val = Parse(v), index })
.First(x => x.val.HasValue);
int start = first.val.Value - n * first.index;
List<string> values = items
.Select((x,i) => (i * n + start).ToString())
.ToList();
}
int? Parse(string strVal)
{
int ret;
if (int.TryParse(strVal, out ret))
{
return ret;
}
return null;
}
Seems like a lot of work to do something kinda simple. Here is a non linq approach.
private List<int> getVals(List<string> input, int modifier)
{
if (input == null) return null; if (input.Count < 1) return null;
foreach (var s in input)
{
int i;
try{i = Convert.ToInt32(s);}
catch{continue;}
var returnList = new List<int>(input.Count);
for (int n = 0; n < input.Count;n++ )returnList[n] = ((n - input.IndexOf(s)) * modifier) + i;
return returnList;
}
return null;
}
DevGeezer's answer, but without the cruft.
But I still learned alot!
static List<String> genlist2(List<String> list, int interval)
{
if (list == null) return null;
var vali = list
.Select((x, i) => x != "N" ? new {val = Convert.ToInt32(x), i } : null)
.First(x => x != null);
if (vali == null) return list.ToList();
return Enumerable.Range(0, list.Count)
.Select(x => (vali.val - (vali.i - x) * interval).ToString())
.ToList();
}

Categories

Resources