0

I am trying to mimic a function that was already created in the code base I am working on. The first function works, but when I try to modify it to use strings in the dictionary it does not work. I get System.Linq.Enumerable+WhereSelectEnumerableIterator2[<>f__AnonymousType32[System.Int32,System.String],System.String] as a value for the comments. I know that the first one is using average which is an aggregate but I cannot figure out how to aggregate the comments as they are strings.

public static Dictionary<int, double> getRatingAverages(string EventID)
        {
        List<tbMultipurposeVertical> allMain = DynamicData.Vertical.getRecords(EventID, appcode, -2).ToList();

        Dictionary<int, double> ratings;

        using (FBCDBDataContext db = new FBCDBDataContext())
            {
            ratings = db.tbMultipurposeVerticals.Where(v => v.eventid == EventID & v.appcode == "ratinglabel" & v.label == "Rater")
                .Select(v => new
                {
                    AbstractID = v.parent,
                    Rating = int.Parse(db.tbMultipurposeVerticals.First(r => r.parent == v.id & r.label == "Rating").value)
                })
                .GroupBy(r => r.AbstractID).ToDictionary(k => k.Key, v => v.Select(r => r.Rating).Average());
            }


        return ratings;
        }


    public static Dictionary<int, string> getRatingComments(string EventID)
    {
        List<tbMultipurposeVertical> allMain = DynamicData.Vertical.getRecords(EventID, appcode, -2).ToList();

        Dictionary<int, string> comments;

        using (FBCDBDataContext db = new FBCDBDataContext())
        {
            comments = db.tbMultipurposeVerticals.Where(v => v.eventid == EventID & v.appcode == "ratinglabel" & v.label == "Rater")
                .Select(v => new 
                {
                    AbstractID = v.parent,
                    Comment = db.tbMultipurposeVerticals.First(r => r.parent == v.id & r.label == "Comment").ToString()

                })
                .GroupBy(r => r.AbstractID).ToDictionary(k => k.Key, v => v.Select(r => r.Comment).ToString());
        }


        return comments;
    }
  • 1
    Try replacing v => v.Select(r => r.Comment).ToString() with v => v.FirstorDefault().Comment. – Steve Greene May 07 '15 at 15:22
  • I would like to concate the values instead of taking the first item. That is where I was getting stuck. – Chris Atwood May 07 '15 at 19:33
  • Yeah, there is probably a complex LINQ statement you could make or you could just group the stuff and use a foreach to compose the result set. http://stackoverflow.com/questions/614542/use-linq-to-concatenate-multiple-rows-into-single-row-csv-property – Steve Greene May 07 '15 at 20:41

1 Answers1

0

In the first method, you are taking the average of the ratings (an aggregate method). For the second method, you are now treating it as a single comment. It's not giving you what you expect because of the .GroupBy()

As Steve Greene suggests, either you can get the first comment (v.First().ToString() or v.FirstOrDefault().ToString()), or you can consider concatenating the comments (v.Concat()) if that makes sense in your application.

Otherwise you may want to make your dictionary to be of the form Dictionary<int, List<string>>

MSzalama
  • 1
  • 2
  • I understand that the group by needs to by used with some aggregate such as average. For my application, I would like to keep the form Dictionary but I do not know how to concatenate the comments. I was looking at something like v => v.Select(r => r.Comment).Aggregate() but was unsure of how to use it. – Chris Atwood May 07 '15 at 18:50
  • @ChrisAtwood I'm not sure how performant it would be, but you can take advantage of `string.Join(string separator, IEnumerable)` (aka: `.ToDictionary(k => k.Key, v => string.Join(" ", v.Select(x => x.Value)))`) https://dotnetfiddle.net/tQeNSa – MSzalama Aug 16 '16 at 18:53