3

The closest solution to what I was looking for is this thread How to flatten nested objects with linq expression

But I get an error trying that approach

The type arguments for method 'System.Linq.Enumerable.SelectMany(System.Collections.Generic.IEnumerable, System.Func>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

My code:

var aa = t.data.SelectMany(x => 
                    x.Value.innerData.SelectMany(y => new { /*Error at this SelectMany*/
                    url = x.Key,
                    disp = x.Value.disp,
                    date = y.Key,
                    count = y.Value.count,
                    rank = y.Value.rank,
       }));

My classes:

public class TData {
    public Dictionary<string, TDetail> data { get; set; }
}

public class TDetail {
    public string disp { get; set; }

    [Newtonsoft.Json.JsonProperty("data")]
    public Dictionary<string, Metrics> innerData { get; set; }

}

public class Metrics {
    public string count { get; set; }
    public string rank { get; set; }
}

The JSON I get from a 3rd party API looks like below:

{
  "data": {
    "abc.com": {
      "disp": "#712176",
      "data": {
        "2015-02-08": {
          "count": 4,
          "rank": 5.8
        },
        "2015-02-23": {
          "count": 3,
          "rank": 8.3
        },
        "2015-03-14": {
          "count": 5,
          "rank": 3.7
        }
      }
    },
    "nbc.com": {
      "disp": "#822176",
      "data": {
        "2015-02-08": {
          "count": 3,
          "rank": 5.5
        },
        "2015-02-23": {
          "count": 5,
          "rank": 8.4
        },
        "2015-03-14": {
          "count": 7,
          "rank": 4.7
        }
      }
    }
  }
}

How do I specify the type arguments explicitly in this case? Thanks.

Community
  • 1
  • 1
Justin
  • 665
  • 9
  • 17

2 Answers2

3

Too many SelectMany:

var t = new TData(); // your TData

var aa = t.data.SelectMany(x =>
        x.Value.innerData.Select(y => new
        {
            url = x.Key,
            disp = x.Value.disp,
            date = y.Key,
            count = y.Value.count,
            rank = y.Value.rank,
        }));

The inner one must be a Select.

xanatos
  • 109,618
  • 12
  • 197
  • 280
  • Your code solves my issue but didn't understand what you meant by "Note that in all of this you are losing the TData.data.Keys, because you are only accessing TData.data.Value". I am using the key of TData as "url" in my final selection. Can you please explain? – Justin Jun 19 '15 at 16:40
  • @Justin Hadn't noticed. – xanatos Jun 19 '15 at 17:44
2

SelectMany projects every individual item into a sequence of items (and then flattens it). Your outer SelectMany is projecting each item into a sequence, but your inner SelectMany is projecting each item into single items that aren't sequences. If you want to project each item in a sequence into a single item then you need to use Select, not SelectMany.

Servy
  • 202,030
  • 26
  • 332
  • 449