0

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

1
  • 1
    "What I am expecting is" - why are you expecting this? Commented May 6, 2022 at 11:27

2 Answers 2

3

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;
}
Sign up to request clarification or add additional context in comments.

7 Comments

Could you shorten this by removing the Where and doing the match on QuotationId in the FirstOrDefault?
@sr28 yes. The original code has also a problem with Default part.
Hi Thanks for your answer, It is working, May I know if there is any issue with original code
@MrPerfect was glad to help! FirstOrDefault will return null if the type is reference type and nothing was matched, so .FirstOrDefault().QuoteLines will throw NRE.
resultSelector: acc => (acc.ints.ToArray(), acc.strs.ToArray() will convert the lists to arrays
|
2

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();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.