How to select multiple elements into array in Linq query? - c#

Net core application. I have below query in my application
var result = sourceProposal.Quotes
.Where(x=>x.QuotationId == sourceQuoteId)
.FirstOrDefault()
.QuoteLines.Select(x=>(x.Quantity,x.WtgType)).ToArray();
This yields in two array elements such as
0 element 1, "string1"
1 element 2, "string2"
What I am expecting is
(int[] sourceQuantity, string[] destinationTurbineType) = sourceProposal.Quotes
.Where(x=>x.QuotationId == sourceQuoteId)
.FirstOrDefault()
.QuoteLines.Select(x=>(x.Quantity,x.WtgType)).ToArray();
I want to copy to tuple which has int[] sourceQuantity, string[] destinationTurbineType this piece of code is not working and throwing error does not contain definition for destructor and no accessible extension method Descontruct accepting first argument of type int(sourceQuantity, string destinationTurbineType)[].
Can someone help me to copy values to sourceQuantity and destinationTurbineType. Any help would be appreciated. Thanks

Select<TSource,TResult> returns enumerable/queryable of the type returned by selector (IEnumerabe<TResult>/IQueryable <TResult>).
If you want to achieve this with LINQ you can use Aggregate:
// note that sourceQuantity and destinationTurbineType would be lists, not arrays
var (sourceQuantity, destinationTurbineType) = sourceProposal.Quotes
.Where(x=>x.QuotationId == sourceQuoteId)
.FirstOrDefault()
.QuoteLines
.Aggregate((ints: new List<int>(), strs: new List<string>()), (aggr, curr) =>
{
aggr.ints.Add(curr.Quantity);
aggr.strs.Add(curr.WtgType);
return aggr;
});
Or just use simple for loop and copy data to destination arrays (possibly move to some extension method). Something along this lines:
var quoteLines = sourceProposal.Quotes
.Where(x=>x.QuotationId == sourceQuoteId)
.FirstOrDefault()
.QuoteLines; // assuming it is materialized collection with indexer like an array or list
int[] sourceQuantity = new int[quoteLines.Length]; // or Count
string[] destinationTurbineType = new string[quoteLines.Count()];
for(int i = 0; i < quoteLines.Length; i++)
{
var curr = quoteLines[i];
sourceQuantity[i] = curr.Quantity;
destinationTurbineType[i] = curr.WtgType;
}

Currently there is no built-in LINQ method to do this. But you could write your own extension method. Something like the following:
public static class EnumerableExtensions
{
public static (TFirst[] xs, TSecond[] ys) Unzip<TFirst, TSecond>(this IEnumerable<(TFirst, TSecond)> zipped)
{
var xs = new List<TFirst>();
var ys = new List<TSecond>();
foreach (var (x, y) in zipped)
{
xs.Add(x);
ys.Add(y);
}
return (xs.ToArray(), ys.ToArray());
}
}
var (xs, ys) =
new[] { 1, 2, 3 }
.Zip(new[] { "a", "b", "c" })
.Unzip();
Console.WriteLine(string.Join(", ", xs)); // 1, 2, 3
Console.WriteLine(string.Join(", ", ys)); // a, b, c
Or in the case of your example, you could then use:
(int[] sourceQuantity, string[] destinationTurbineType) = sourceProposal.Quotes
.Where(x=>x.QuotationId == sourceQuoteId)
.FirstOrDefault()
.QuoteLines.Select(x=>(x.Quantity,x.WtgType)).Unzip();

Related

First found duplicate element using LINQ (Not contiguous)

How do I print the first duplicate elements from an array?
var arr = new int[]{ 3, 2, 5, 1, 5, 4, 2, 15 };
Currently this method print 2 instead of 5.
public int FirstDuplicate(int[] arr)
{
var firstDup = arr
.GroupBy(x => x)
.Where(grp => grp.Count() == 2)
.Select(grp => grp.Key)
.FirstOrDefault();
if (firstDup > 0) return firstDup;
return -1;
}
You can write an extension metod that will return all duplicates from an IEnumerable<T> like
public static class EnumerableExtensions
{
public static IEnumerable<T> Duplicates<T>( this IEnumerable<T> source )
{
var hashset = new HashSet<T>();
foreach ( var item in source )
{
if ( hashset.Contains(item) )
yield return item;
else
hashset.Add(item);
}
}
}
and then use it
var arr = new int[]{ 3, 2, 5, 5, 4, 2, 15 };
var firstDuplicate = arr.Duplicates().First();
see .net fiddle example
This worked for me. I took advantage of comparing values with array indexes, the Distinct() method, and the first element of the resulting array.
var arr = new int[] { 3, 2, 5, 5, 4, 2, 15 };
var adjacentDuplicate = arr.Skip(1) // Skip first
.Where((value,index) => value == arr[index])
.Distinct()
.ToArray(); // Convert to array
if (adjacentDuplicate.Any())
{
Console.WriteLine(adjacentDuplicate[0]); // Print first duplicate
}
else
{
// No duplicates found.
}
Based on Sir Rufo answer, I would make two extensions
public static IEnumerable<T> Duplicates<T>(this IEnumerable<T> source)
{
var hashset = new HashSet<T>();
foreach (var item in source)
{
if (!hashset.Add(item))
{
yield return item;
}
}
}
public static IEnumerable<T?> AsNullable<T>(this IEnumerable<T> source) where T : struct
{
return source.Select(x => (T?)x);
}
You can use it like
var duplicate = arr
.Duplicates()
.AsNullable()
.FirstOrDefault();
The AsNullableconverts int into int? without hard coding the type. When the result is null, there is no duplicity. You can use it in more situations, like calculating the Max of potentially empty sequence of non nullable values (you can define it for IQueryable too). The advantage of this extension is, that when you use it, you know for sure, that null is not valid value in the source. And you would not shoot yourself into the leg when the null suddenly becomes a possible value.

LINQ swap columns into rows

Is there a fancy LINQ expression that could allow me to do the following in a much more simpler fashion. I have a List<List<double>>, assuming the List are columns in a 2d matrix, I want to swap the list of columns into a list of rows. I have the following obvious solution:
int columns = 5;
var values; // assume initialised as List<List<double>>()
var listOfRows = new List<List<double>>();
for (int i = 0; i < columns ; i++)
{
List<double> newRow = new List<double>();
foreach (List<double> value in values)
{
newRow.Add(value[i]);
}
listOfRows.Add(newRow);
}
You could LINQify the inner loop pretty easily:
vector.AddRange(values.Select(value => value[i]));
Whether or not that improves the readability is left entirely up to you!
Here's a Linq expression that would do what you want - looking at it I'd personally stick with the nested foreach loops though - much easier to read:
var columnList= new List<List<double>>();
columnList.Add(new List<double>() { 1, 2, 3 });
columnList.Add(new List<double>() { 4, 5, 6 });
columnList.Add(new List<double>() { 7, 8, 9 });
columnList.Add(new List<double>() { 10, 11, 12 });
int columnCount = columnList[0].Count;
var rowList = columnList.SelectMany(x => x)
.Select((x, i) => new { V = x, Index = i })
.GroupBy(x => (x.Index + 1) % columnCount)
.Select(g => g.Select( x=> x.V).ToList())
.ToList();
This example also would only work on a matrix with a fixed column count. Basically it's flattening the matrix into a list, then creating the list of rows by grouping by the index of the element in the list modulo the column count.
Edit:
A different approach, much closer to a nested loop and probably similar performance besides the overhead.
int columnCount = columnList[0].Count;
int rowCount = columnList.Count;
var rowList = Enumerable.Range(0, columnCount)
.Select( x => Enumerable.Range(0, rowCount)
.Select(y => columnList[y][x])
.ToList())
.ToList();
var inverted = Enumerable.Range(0, columnCount)
.Select(index => columnList.Select(list => list[index]));
In short, we enumerate the column index from a range and use it to collect the nth element of each list.
Please note that you'll need to check that every list has the same number of columns.
Here's one that works for rectangular (non-ragged) matrices. The C# code here works cut-and-paste into LinqPad, a free, interactive C# programming tool.
I define a postfix operator (that is, an extension method) "Transpose." Use the operator as follows:
var rand = new Random();
var xss = new [] {
new [] {rand.NextDouble(), rand.NextDouble()},
new [] {rand.NextDouble(), rand.NextDouble()},
new [] {rand.NextDouble(), rand.NextDouble()},
};
xss.Dump("Original");
xss.Transpose().Dump("Transpose");
resulting in something like this:
Original
0.843094345109116
0.981432441613373
0.649207864724662
0.00594645645746331
0.378864820291691
0.336915332515219
Transpose
0.843094345109116
0.649207864724662
0.378864820291691
0.981432441613373
0.00594645645746331
0.336915332515219
The gist of the implementation of this operator is the following
public static IEnumerable<IEnumerable<T>> Transpose<T>(this IEnumerable<IEnumerable<T>> xss)
{
var heads = xss.Heads();
var tails = xss.Tails();
var empt = new List<IEnumerable<T>>();
if (heads.IsEmpty())
return empt;
empt.Add(heads);
return empt.Concat(tails.Transpose());
}
Here is the full implementation, with some lines commented out that you can uncomment to monitor how the function works.
void Main()
{
var rand = new Random();
var xss = new [] {
new [] {rand.NextDouble(), rand.NextDouble()},
new [] {rand.NextDouble(), rand.NextDouble()},
new [] {rand.NextDouble(), rand.NextDouble()},
};
xss.Dump("Original");
xss.Transpose().Dump("Transpose");
}
public static class Extensions
{
public static IEnumerable<T> Heads<T>(this IEnumerable<IEnumerable<T>> xss)
{
Debug.Assert(xss != null);
if (xss.Any(xs => xs.IsEmpty()))
return new List<T>();
return xss.Select(xs => xs.First());
}
public static bool IsEmpty<T>(this IEnumerable<T> xs)
{
return xs.Count() == 0;
}
public static IEnumerable<IEnumerable<T>> Tails<T>(this IEnumerable<IEnumerable<T>> xss)
{
return xss.Select(xs => xs.Skip(1));
}
public static IEnumerable<IEnumerable<T>> Transpose<T>(this IEnumerable<IEnumerable<T>> xss)
{
// xss.Dump("xss in Transpose");
var heads = xss.Heads()
// .Dump("heads in Transpose")
;
var tails = xss.Tails()
// .Dump("tails in Transpose")
;
var empt = new List<IEnumerable<T>>();
if (heads.IsEmpty())
return empt;
empt.Add(heads);
return empt.Concat(tails.Transpose())
// .Dump("empt")
;
}
}
I am combining some of the answers above, which sometimes had columns and rows inverted form the original answer or from the convention I am used to : row refers to the first index and column to the inner ( second) index. e.g. values[row][column]
public static List<List<T>> Transpose<T>(this List<List<T>> values)
{
if (values.Count == 0 || values[0].Count == 0)
{
return new List<List<T>>();
}
int ColumnCount = values[0].Count;
var listByColumns = new List<List<T>>();
foreach (int columnIndex in Enumerable.Range(0, ColumnCount))
{
List<T> valuesByColumn = values.Select(value => value[columnIndex]).ToList();
listByColumns.Add(valuesByColumn);
}
return listByColumns;
}
Actually the word row and column is just our convention of thinking about the data in rows and columns , and sometimes adds more confusion than solving them.
We are actually just swapping the inner index for the outer index. (or flipping the indexes around). So one could also just define the following extension method. . Again I borrowed from above solutions, just put it into something I find readable and fairly compact.
Checks that the inner lists are of equal sized are required.
public static List<List<T>> InsideOutFlip<T>(this List<List<T>> values)
{
if (values.Count == 0 || values[0].Count == 0)
{
return new List<List<T>>();
}
int innerCount = values[0].Count;
var flippedList = new List<List<T>>();
foreach (int innerIndex in Enumerable.Range(0, innerCount))
{
List<T> valuesByOneInner = values.Select(value => value[innerIndex]).ToList();
flippedList.Add(valuesByOneInner);
}
return flippedList;
}

C#: Altering values for every item in an array

I'm wondering if there is built-in .NET functionality to change each value in an array based on the result of a provided delegate. For example, if I had an array {1,2,3} and a delegate that returns the square of each value, I would like to be able to run a method that takes the array and delegate, and returns {1,4,9}. Does anything like this exist already?
LINQ provides support for projections using the Select extension method:
var numbers = new[] {1, 2, 3};
var squares = numbers.Select(i => i*i).ToArray();
You can also use the slightly less fluent Array.ConvertAll method:
var squares = Array.ConvertAll(numbers, i => i*i);
Jagged arrays can be processed by nesting the projections:
var numbers = new[] {new[] {1, 2}, new[] {3, 4}};
var squares = numbers.Select(i => i.Select(j => j*j).ToArray()).ToArray();
Multidimensional arrays are a little more complex. I've written the following extension method which projects every element in a multidimensional array no matter what its rank.
static Array ConvertAll<TSource, TResult>(this Array source,
Converter<TSource, TResult> projection)
{
if (!typeof (TSource).IsAssignableFrom(source.GetType().GetElementType()))
{
throw new ArgumentException();
}
var dims = Enumerable.Range(0, source.Rank)
.Select(dim => new {lower = source.GetLowerBound(dim),
upper = source.GetUpperBound(dim)});
var result = Array.CreateInstance(typeof (TResult),
dims.Select(dim => 1 + dim.upper - dim.lower).ToArray(),
dims.Select(dim => dim.lower).ToArray());
var indices = dims
.Select(dim => Enumerable.Range(dim.lower, 1 + dim.upper - dim.lower))
.Aggregate(
(IEnumerable<IEnumerable<int>>) null,
(total, current) => total != null
? total.SelectMany(
item => current,
(existing, item) => existing.Concat(new[] {item}))
: current.Select(item => (IEnumerable<int>) new[] {item}))
.Select(index => index.ToArray());
foreach (var index in indices)
{
var value = (TSource) source.GetValue(index);
result.SetValue(projection(value), index);
}
return result;
}
The above method can be tested with an array of rank 3 as follows:
var source = new int[2,3,4];
for (var i = source.GetLowerBound(0); i <= source.GetUpperBound(0); i++)
for (var j = source.GetLowerBound(1); j <= source.GetUpperBound(1); j++)
for (var k = source.GetLowerBound(2); k <= source.GetUpperBound(2); k++)
source[i, j, k] = i*100 + j*10 + k;
var result = (int[,,]) source.ConvertAll<int, int>(i => i*i);
for (var i = source.GetLowerBound(0); i <= source.GetUpperBound(0); i++)
for (var j = source.GetLowerBound(1); j <= source.GetUpperBound(1); j++)
for (var k = source.GetLowerBound(2); k <= source.GetUpperBound(2); k++)
{
var value = source[i, j, k];
Debug.Assert(result[i, j, k] == value*value);
}
Not that I'm aware of (replacing each element rather than converting to a new array or sequence), but it's incredibly easy to write:
public static void ConvertInPlace<T>(this IList<T> source, Func<T, T> projection)
{
for (int i = 0; i < source.Count; i++)
{
source[i] = projection(source[i]);
}
}
Use:
int[] values = { 1, 2, 3 };
values.ConvertInPlace(x => x * x);
Of course if you don't really need to change the existing array, the other answers posted using Select would be more functional. Or the existing ConvertAll method from .NET 2:
int[] values = { 1, 2, 3 };
values = Array.ConvertAll(values, x => x * x);
This is all assuming a single-dimensional array. If you want to include rectangular arrays, it gets trickier, particularly if you want to avoid boxing.
Using System.Linq you could do something like:
var newArray = arr.Select(x => myMethod(x)).ToArray();
LINQ queries could easily solve this for you - make sure you're referencing System.Core.dll and have a
using System.Linq;
statement. For example, if you had your array in a variable named numberArray, the following code would give you exactly what you're looking for:
var squares = numberArray.Select(n => n * n).ToArray();
The final "ToArray" call is only needed if you actually need an array, and not an IEnumerable<int>.
you can use linq to accomplish this in shorthand but be careful remember that a foreach occurs underneath anyway.
int[] x = {1,2,3};
x = x.Select(( Y ) => { return Y * Y; }).ToArray();
Here is another solution for M x N arrays, where M and N are not known at compile time.
// credit: https://blogs.msdn.microsoft.com/ericlippert/2010/06/28/computing-a-cartesian-product-with-linq/
public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(IEnumerable<IEnumerable<T>> sequences)
{
IEnumerable<IEnumerable<T>> result = new[] { Enumerable.Empty<T>() };
foreach (var sequence in sequences)
{
// got a warning about different compiler behavior
// accessing sequence in a closure
var s = sequence;
result = result.SelectMany(seq => s, (seq, item) => seq.Concat<T>(new[] { item }));
}
return result;
}
public static void ConvertInPlace(this Array array, Func<object, object> projection)
{
if (array == null)
{
return;
}
// build up the range for each dimension
var dimensions = Enumerable.Range(0, array.Rank).Select(r => Enumerable.Range(0, array.GetLength(r)));
// build up a list of all possible indices
var indexes = EnumerableHelper.CartesianProduct(dimensions).ToArray();
foreach (var index in indexes)
{
var currentIndex = index.ToArray();
array.SetValue(projection(array.GetValue(currentIndex)), currentIndex);
}
}

how to split list using linq

i have List of int which consists of value 0,0,0,1,2,3,4,0,0 now i like to split this into 3 lists like this list A consists 0,0,0 and List B consists 1,2,3,4 and List C consists 0,0.I know how split using if and for,but how can i do this using linq. usual format i need split in starting some zeros and in middle some values and in last some zeros i need to split this first zeros in one list ,middle values in one list and end zeros in another list as i say in example above here using linq and also i like to take the index that values.
first one.
myList.TakeWhile(x => x==0)
second one.
myList.SkipWhile(x => x==0).TakeWhile(x => x!= 0)
third one.
myList.SkipWhile(x => x==0).SkipWhile(x => x!= 0)
If you want to split by zero sequence then try this code:
static void Main(string[] argv)
{
var list = new[] { 0, 0, 0, 1, 2, 3, 4, 0, 0 };
int groupIndex = 0;
var result = list.Select(
(e, i) =>
{
if (i == 0)
{
return new {val = e, group = groupIndex};
}
else
{
groupIndex =
(e != 0 && list[i - 1] == 0) || (e == 0 && list[i - 1] != 0)
?
groupIndex + 1
: groupIndex;
return new {val = e, group = groupIndex};
}
}
).GroupBy(e => e.group).Select(e => e.Select(o => o.val).ToList()).ToList();
foreach (var item in result)
{
foreach (var val in item)
{
Console.Write(val + ";");
}
Console.WriteLine();
Console.WriteLine("Count:" + item.Count);
Console.WriteLine();
}
Console.ReadLine();
}
Output is:
0;0;0;
Count:3
1;2;3;4;
Count:4
0;0;
Count:2
It is really not clear what is a criteria of split from your question. If I gave wrong answer then explain your question.
You can use the Skip and Take methods exposed by Linq to Objects to grab certain elements of a sequence.
var myList = new int[] {0,0,0,1,2,3,4,0,0};
var list1 = myList.Take(3);
var list2 = myList.Skip(3).Take(4);
var list3 = myList.Skip(7);
You can use Take(n) or Skip(n) in linq
List<int> list = new List<int>();
list.Add(0);
list.Add(0);
list.Add(0);
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
list.Add(0);
list.Add(0);
var listOne = list.Take(3);
var listSecond = list.Skip(3).Take(4);
var listThird = list.Skip(7);

Convert string[] to int[] in one line of code using LINQ

I have an array of integers in string form:
var arr = new string[] { "1", "2", "3", "4" };
I need to an array of 'real' integers to push it further:
void Foo(int[] arr) { .. }
I tried to cast int and it of course failed:
Foo(arr.Cast<int>.ToArray());
I can do next:
var list = new List<int>(arr.Length);
arr.ForEach(i => list.Add(Int32.Parse(i))); // maybe Convert.ToInt32() is better?
Foo(list.ToArray());
or
var list = new List<int>(arr.Length);
arr.ForEach(i =>
{
int j;
if (Int32.TryParse(i, out j)) // TryParse is faster, yeah
{
list.Add(j);
}
}
Foo(list.ToArray());
but both looks ugly.
Is there any other ways to complete the task?
Given an array you can use the Array.ConvertAll method:
int[] myInts = Array.ConvertAll(arr, s => int.Parse(s));
Thanks to Marc Gravell for pointing out that the lambda can be omitted, yielding a shorter version shown below:
int[] myInts = Array.ConvertAll(arr, int.Parse);
A LINQ solution is similar, except you would need the extra ToArray call to get an array:
int[] myInts = arr.Select(int.Parse).ToArray();
EDIT: to convert to array
int[] asIntegers = arr.Select(s => int.Parse(s)).ToArray();
This should do the trick:
var asIntegers = arr.Select(s => int.Parse(s));
To avoid exceptions with .Parse, here are some .TryParse alternatives.
To use only the elements that can be parsed:
string[] arr = { null, " ", " 1 ", " 002 ", "3.0" };
int i = 0;
var a = (from s in arr where int.TryParse(s, out i) select i).ToArray(); // a = { 1, 2 }
or
var a = arr.SelectMany(s => int.TryParse(s, out i) ? new[] { i } : new int[0]).ToArray();
Alternatives using 0 for the elements that can't be parsed:
int i;
var a = Array.ConvertAll(arr, s => int.TryParse(s, out i) ? i : 0); //a = { 0, 0, 1, 2, 0 }
or
var a = arr.Select((s, i) => int.TryParse(s, out i) ? i : 0).ToArray();
C# 7.0:
var a = Array.ConvertAll(arr, s => int.TryParse(s, out var i) ? i : 0);
you can simply cast a string array to int array by:
var converted = arr.Select(int.Parse)
var asIntegers = arr.Select(s => int.Parse(s)).ToArray();
Have to make sure you are not getting an IEnumerable<int> as a return
var list = arr.Select(i => Int32.Parse(i));

Categories