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
CodePudding user response:
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;
}
CodePudding user response:
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();