tags:

views:

80

answers:

2

I'm new to LINQ, and I have trouble with a query I'm trying to write to teach myself LINQ.

I have a list of MyError objects. A MyError object has a errorcode (an enum) and an arraylist of MyEntryError objects. Some MyError may have the same errorcode.

I would like to create a LINQ query that take as input my list of MyError and outputs a new list of MyError so that, for each errorcode, there is only one MyError that will contain all the MyEntryError that failed with the errorcode of the MyError.

What I mean is let's say I have a list of MyError objects such as this one :

  • MyError1 : errorcode = ErrorType1 Arraylist : A, C
  • MyError2 : errorcode = ErrorType2 ArrayList : B, D, E
  • MyError3 : errorcode = ErrorType2 ArrayList : F
  • MyError4 : errorcode = ErrorType1 ArrayList : G
  • MyError5 : errorcode = ErrorType3 ArrayList : Z

My desired output is a list of MyError objects with the following objects :

  • MyError1 : errorcode = ErrorType1 ArrayList : A, C, G
  • MyError2 : errorcode = ErrorType2 ArrayList : B, D, E, F
  • MyError3 : errorcode = ErrorType3 ArrayList : Z

Is it possible with LINQ ? If so, How ?

I'm guessing that using an ArrayList instead of a List in the MyError class may be a problem so if it can't be done with an ArrayList, i would like to see a query that would works with a modified MyError class that uses a List

Thanks in advance

+1  A: 

something like, where errorList is your list of MyError1 t/m MyError5, and your arraylist is called errors.

from err in errorList
group err by err.errorcode into g
select new MyError { errorcode = g.Key, errors = new ArrayList(g.SelectMany(a => a.errors.Cast<YourType>()).ToArray()) };
Jan Jongboom
Your solution is interesting, but it doesn't exactly output MyError objects : it output a new object with an errorcode and an IEnumerable<YourErrorType> which is actually fine for my actual need, but not exactly a "perfect" answer. I'm trying to fiddle with it to try to make it generates a MyError object with its ArrayList.
Ksempac
this results in a list of anonymous objects, not a list of MyError objects...
jeroenh
Edited to return a `MyError`.
Jan Jongboom
+2  A: 
    public List<MyError> GroupErrorsByErrorCode(List<MyError> errors)
    {
        var result = errors.GroupBy(e => e.ErrorCode).Select(group => new MyError
            {
                ErrorCode = group.Key,
                // EDIT: was 
                // Errors = group.SelectMany(g => g.Errors)
                Errors = new ArrayList(group
                           .SelectMany(g => g.Errors.Cast<MyEntryError>())
                           .ToList())
            });
        return result;
    }

EDIT: As ArrayList has a constructor that takes an ICollection, you can use that overload to instantiate the Errors property.

Using a strongly typed list instead of ArrayList is always a good idea...

jeroenh
I know that generic are better, the thing is, I extracted this exercise while working on a real project. In the real project, I can't change the classes because they are generated and I don't have access to the classes or the generator (yeah i know generated code is evil, but once again I'm not the one who makes the decision...).
Ksempac
It is possible with an ArrayList, just check my answer.
Jan Jongboom
@Jan Jongboom: The question states that the output should be a list of MyError objects. Here the result is a list of anonymous objects. If MyError.Errors is a property of type ArrayList, I don't see how you would instantiate it.
jeroenh
Yup jeroenh is right, that's why I was trying to modify Jan's solution before commenting about it.
Ksempac
I updated my answer to instantiate the Errors property as an ArrayList. I find it ugly like that, though I understand the difficulty of refactoring when working on legacy code ;-)
jeroenh
Ah well, now I see you edited too. :-)
Jan Jongboom
Congratulations, it works :) I actually tried this kind of thing but messed up with the constructor (tried to use ToArray instead of ToList). (Also good idea to keep your old answer as commented code).
Ksempac