1

I'm iterating through objects that contains an array of doubles. Names changed. Imagine this is an object of Lab samples, and I'm trying to get a flat representation of the Sample object.

From:

Sample
{
    public string Name
    public string Type
    ...
    public double[] RawReadings
}

To, for example:

Name,
RawRead1,
RawRead2,
RawRead3,
...
RawReadn

How do I finangle sample.RawReadings to give me all n items in the array? I don't care if it's named or not.

Edit for clarity: I want the each item in the resulting list to have the Name and as many doubles as properties in the class as there are RawReads. I do not want each item in the resulting list to have a Name and an array - that'll just be the same as what I had.

Sample LinQ:

from sample in Samples
select new
{
    Name = sample.Name,
    sample.RawReadings
}

Is this even possible?

Edit: I'm feeding this to a 3rd party API call that's expecting something in a "row and column format". Aspose.Cells ImportCustomObject to be exact. It might be possible to work around it with multiple calls and manually aligning them but that can be tricky and bug prone.

Jeremy Thompson
  • 61,933
  • 36
  • 195
  • 321
Tan
  • 23
  • 4
  • 1
    Your question isn't clear. Do you want a resulting list of objects that contain the name and the reading for reach raw reading in sample? – David L Sep 15 '15 at 14:57
  • That's right, but the resulting list of raw readings shouldn't but in an array contained in the each item of the list. In other words, the list shouldn't hold Name and List, but Name and n doubles. – Tan Sep 15 '15 at 14:59
  • Do you want to flatten to `FlattenedSample { Name, Type, Reading }`? – Dave Zych Sep 15 '15 at 14:59
  • How would you expect a class to hold n doubles? Do you mean n individual properties, each representing a RawReading? If you did want to do this, why? You already have a collection. – David L Sep 15 '15 at 15:02
  • Thanks for the comments. I edited my question to clarify. – Tan Sep 15 '15 at 15:02
  • 1
    This guy asked a very similar question 15 mins ago: http://stackoverflow.com/q/32588070/495455 – Jeremy Thompson Sep 15 '15 at 15:03
  • I'm still confused, you want an extra property added to your class for every reading in the array? – DavidG Sep 15 '15 at 15:03
  • Do you mean you want to pivot this into a structure with a Name and then n double properties for each value of the array? – juharr Sep 15 '15 at 15:04
  • 3
    @JeremyThompson it's only slightly similar. It looks like the OP wants to actually add a property for every double in RawReadings. – David L Sep 15 '15 at 15:04
  • 2
    Maybe you should explain why you are attempting to do that in the first place as you might be asking a [XY Problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) – juharr Sep 15 '15 at 15:06
  • Yes, I do want to have n double properties for each double in RawReadings. I came across SelectMany but don't think that works for me. IME that's to flatten a n+1 dimensional array into a n dimensional array. – Tan Sep 15 '15 at 15:06
  • How do you expect to access n different properties? And in what way would it be different between `sample.Reading1` and `sample.Reading[0]`? – DavidG Sep 15 '15 at 15:07
  • @juharr - I'm feeding this to a 3rd party API call that's expecting something in a "row and column format". Aspose.Cells ImportCustomObject to be exact. It might be possible to work around it with multiple calls and manually aligning them but that can be tricky and bug prone. – Tan Sep 15 '15 at 15:09
  • @DavidL yeah and as you said the question isn't clear, the OP should show a better output of what they want. Anyway its always interesting when you see 2 questions with basically the same title in a row. Cheers – Jeremy Thompson Sep 15 '15 at 15:10
  • FTR I don't know the person who asked the other question, Cedric Druck. Odd coincidence to a somewhat similar but quite different question. – Tan Sep 15 '15 at 15:13

3 Answers3

6

I want the each item in the resulting list to have the Name and as many doubles as there are RawReads.

You can't do that using anonymous types. Anonymous types have property names and types specified at compile-time whereas you're wanting to specify them at execution-time. It's not clear why you're trying to do this, but the closest you could come would be to use dynamic typing, for which you could use an expando:

public dynamic SampleToDynamic(Sample sample)
{
    IDictionary<string, object> expando = new ExpandoObject();
    expando["Name"] = sample.Name;
    for (int i = 0; i < sample.RawReadings.Length; i++)
    {
        expando["RawRead" + (i + 1)] = sample.RawReadings[i];
    }
    return expando;
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thank you. I could've implemented another solution but got curious if this was even possible. Your response makes makes sense to me and was educational. I'll leave this open for a bit in case more brilliant hacks gets dreamed up. :) – Tan Sep 15 '15 at 15:18
  • sample.RawReadings.Count() – Arghya C Sep 15 '15 at 16:52
  • 1
    @ArghyaC: Whoops, thought it was a `List`. Changed to `Length`. – Jon Skeet Sep 15 '15 at 16:53
4

Suppose you have sample data like this(here I have represented RawReadings as comma separated but in actual they are array of double):-

Name     Type      RawReadings
--------------------------------
foo      bar         1.2, 3.5, 4.8
foo1     bar1        8.3, 6.6

As far as I have understood, you need all the RawReadings values to fetched as new properties with Name & Type. But as already explained by @JonSkeet, it's not possible. What is possible is to flatten the RawReadings data and combine it with other properties of Sample class like this:-

Name     Type     RawReadings
--------------------------------
foo      bar       1.2
foo      bar       3.5
foo      bar       4.8
foo1     bar1      8.3
foo1     bar1      6.6

Here is the code for this:-

var result = sampleData
         .SelectMany(x => x.RawReadings, (sampleObj, rawObj) => new { sampleObj, rawObj })
         .Select(x => new
                     {
                          Name = x.sampleObj.Name,
                          Type = x.sampleObj.Type,
                          raws = x.rawObj
                      });
Rahul Singh
  • 21,585
  • 6
  • 41
  • 56
  • Thanks, I am indeed looking for the not possible case. With just a single foo, and a single bar. Like: foo bar 1.2 3.5 4.8 ; foo1 bar1 8.3 6.6 – Tan Sep 15 '15 at 18:38
0

Assuming you have data like,

var samples = new List<Sample>();
samples.Add(new Sample { Name = "A", Type = "TypeA", RawReadings = new double[] { 1.5, 2.5, 3.5 } });
samples.Add(new Sample { Name = "B", Type = "TypeB", RawReadings = new double[] { 1.6, 2.6, 3.6 } });

You want something like

A 1.5
A 2.5
A 3.5
B 1.6
B 2.6
C 3.6

You can use this code

var sampleReadings = new List<KeyValuePair<string, double>>();
samples.ForEach(s => 
            s.RawReadings.ToList().ForEach(r => 
                                    sampleReadings.Add(new KeyValuePair<string, double>(s.Name, r))));
Arghya C
  • 9,805
  • 2
  • 47
  • 66