-1

I have the following problem: I want to read workers data from a text file, which is formatted; worker_id;name;surname;login;. And then write it to another file only containing lines without duplicate logins.

When I create class worker , List<workers> and try this code:

List<worker> unics = workers
           .GroupBy(w => w.login)
           .Select(g => g.First())
           .ToList();

Where string login = line1.Split(';')[3];, everything is OK.

But when I use Lambdas without creating class worker (which is NOT necessary for me at the moment), it doesn't work.

List<string> unicsL = list1            //list1 - list of all lines1 in file      
           .GroupBy(x => x.Split(';')[3])  //ERROR - NullReferenceException // - Use new keyword to create object instance...
           .Select(g => g.First())         
           .ToList();

What is the problem?

Kolky
  • 2,917
  • 1
  • 21
  • 42
Jack
  • 13
  • 3
  • 4
    Show how `list1` and `workers` are populated. All we know they are some `IEnumerable`. Or simply check yourself: [click](http://stackoverflow.com/q/4660142/1997232). – Sinatr Apr 01 '16 at 09:54
  • Any blank lines? or any lines that don't have all 3 `;` ? – freedomn-m Apr 01 '16 at 10:06
  • Lines are the same in both cases : if you build a class worker using them everything is OK but when you try to find 'proper lines' - it doesn't work : i.e. I don't know HOW to build this lambda. – Jack Apr 01 '16 at 10:25
  • It depends on how you populate your worker class. There's nothing wrong with the linq statement itself - if `x` is null, you get the error in the first code, `w.login` may just be an empty string if the source row is empty, so will not give a null ref error. – freedomn-m Apr 01 '16 at 10:30

2 Answers2

1

You get a null reference because x is null- ie one of your entries in list1 is null.

You can check for this before making group:

        List<string> unicsLx = list  
           .Where(x=> x != null)
           .GroupBy(x => x.Split(';')[3])
           .Select(g => g.First())         
           .ToList();

A better option would be to use IsNullOrWhiteSpace():

        List<string> unicsLx = list  
           .Where(x=> !string.IsNullOrWhiteSpace(x))
           .GroupBy(x => x.Split(';')[3])
           .Select(g => g.First())         
           .ToList();

However, you'll quickly get another issue where there aren't 3x ; (or the last one is empty), so you can add that check as well:

        .Where(x => !string.IsNullOrWhiteSpace(x) && x.Split(';').Length > 2 && !string.IsNullOrWhiteSpace(x.Split(';')[3]))

However, this means you're applying the Split multiple times (twice here and again on the group), so you can remove one of these by adding a Select:

    // Example data
    var list = new[] { "a;b;c;d", null, "w;x;y;z;", "m;m;m;d", "", "one;two", "empty;empty;empty;" };

    List<string> unicsL = list
        .Where(x => !string.IsNullOrWhiteSpace(x) && x.Split(';').Length > 2)
        .Select(x => x.Split(';')[3])
        .Where(x => !string.IsNullOrWhiteSpace(x))
        .GroupBy(x => x)
        .Select(g => g.First())
        .ToList();
freedomn-m
  • 27,664
  • 8
  • 35
  • 57
  • YES : .Where(x=> !string.IsNullOrWhiteSpace(x)) - THIS SOLVED my problem :) I found the problem was 'somwhere in file' . Though it was simple text file , read by ReadLine() method. But when I used myList.Add("something;something;....) - 'manually' everything went OK. After adding Your : .Where...clause this ERROR disappeared. So THANK YOU VERY MUCH :) – Jack Apr 01 '16 at 10:50
  • You, @freedomn-m, still have a double split on most lines. You could also, after your where, select a split, then where for length & null-or-whitespace, then select the 4th option (3rd index). `.Where(x => !string.IsNullOrWhiteSpace(x)).Select(x => x.Split(';')).Where(x => x.Length > 2 && !string.IsNullOrWhiteSpace(x[3])).Select(x => x[3])` – Kolky Apr 01 '16 at 11:01
  • @Kolky Agreed - it's worth noting that there will still be two splits in this code. Whether it's worth the additional complication or taking the hit depends on how many lines there are any time requirements (eg must it be done as quickly as possible), in which case there are probably better ways to handle this than using `GroupBy`. – freedomn-m Apr 01 '16 at 11:05
  • @freedomn-m I agree, it is kinda useless in most cases ;) – Kolky Apr 01 '16 at 11:09
0

Use this.

List<string> unicsL = list1            //list1 - list of all lines1 in file      
           .Where(x=>!string.IsNullOrEmpty(x))
           .GroupBy(x => new {key = x.Split(';')[3]})  
           .Select(g => g.First())         
           .ToList();
Hari Prasad
  • 16,716
  • 4
  • 21
  • 35