Click here to Skip to main content
15,075,944 members
Please Sign up or sign in to vote.
2.71/5 (3 votes)
See more:
Hi :)

I try to read a simple TXT file using Linq, but, my dificult is. read a file in 2 by 2 lines, for this, I made a simple function, but, I belive I can read the TXT separating 2 by 2 lines...

My code to read the text lines is:

C#
private struct Test
{
    public string Line1, Line2;
};

static List<Test> teste_func(string[] args)
{
    List<Test> exemplo = new List<Test>();
    var lines = File.ReadAllLines(args[0]).Where(x => x.StartsWith("1") || x.StartsWith("7")).ToArray();

    for(int i=0;i<lines.Length;i++)
    {
        Test aux = new Test();
        aux.Line1 = lines[i];
        i+=1;
        aux.Line2 = lines[i];

        exemplo.Add(aux);
    }

    return exemplo;
}


Before I create this function, I tried to do this:

C#
var lines = File.ReadAllLines(args[0]). .Where(x=>x.StartsWith("1") || x.StartsWith("7")).Select(x =>
                new Test
                {
                    Line1 = x.Substring(0, 10),
                    Line2 = x.Substring(0, 10)
                });


But, it's obvious, that system will be get line by line and create a new struct for the line...
So, how I can make to get 2 by 2 lines with linq ?
Posted
Comments
Matt T Heffron 31-Oct-13 13:49pm
   
What does your file look like?
This will collect all of the lines that start with either a 1 or a 7.
Then the first example will go through all of the lines in pairs, assigning the even numbered ones into the Line1 field and odd numbered ones into Line2.
If I understand the problem this is correct.
So what additional information can you supply?
What is the symptom you're seeing?

As I look at your code, I see this:

in the first example:

0. your Linq selection function that creates an array looks okay.

1. you are not really "reading" the file with Linq; you are using Linq to select lines of the read file based on criteria.

2. you are incrementing the 'for loop counter inside the scope of the 'for loop block: this is usually something that leads to disaster.

Of course, that's easily taken care of by: for (int i = 0; i < lines.Length; i += 2) {}

3. your code suggests that every time you find a match the next line in the file will contain another match: is this assumption correct ?

So, is your code working for you now ? If it isn't, what problems do you see ? Are you using this on very large files ?
   
v2
Quote:
So, how I can make to get 2 by 2 lines with linq ?

I strongly urge you to stay with your non-LINQ code as it will be much easier to understand and change (if needed) later on. Do however, make the changes that Bill Woodruff has suggested.

With that said, it can be fun to see what you can force LINQ to achieve :0 even if the resulting code is a nightmare to read and maintain:~.

Here are two ways that came to mind to achieve this in LINQ.
C#
// lines is used to simulate ReadAllLines function result
string[] lines = {"1 abc","2 abc","7 abc","7 efd","4 mno","1 xyz","7 nope"};

string[] filteredlines = lines.Where((string x) => x.StartsWith("1") || x.StartsWith("7")).ToArray();

List<test> BadIdea;
// note: (index & 1) == 0) is a way to check if index is an even number
//        index is the LINQ enumerator index
BadIdea = filteredlines.Where((string dummy, Int32 index) => (((index & 1) == 0) && (index <= (filteredlines.Length / 2)) && (filteredlines.Length > 1))).
                        Select((string dummy, Int32 index) => 
                        new Test {Line1 = filteredlines[index * 2],	Line2 = filteredlines[(index * 2) + 1]}).ToList();


List<test> ReallyBadIdea = default(List<test>);

// to get it all into one LINQ statement
// I use a dummy integer array with one element to enumerate over
// the temp variable tmpFilteredLines pulls in the lines to enumerate over
// as above, lines() replaces ReadAllLines function

ReallyBadIdea = (List<test>)(from dummyvar in new Int32[] {1}
                             let tmpFilteredLines = lines.Where((string x) => x.StartsWith("1") || x.StartsWith("7")).ToArray()
                             select (tmpFilteredLines.Where((string dummy, Int32 index) => 
                                 (((index & 1) == 0) && (index <= (tmpFilteredLines.Length / 2)) && (tmpFilteredLines.Length > 1))).
                             Select((string dummy, Int32 index) => new Test() { Line1 = tmpFilteredLines[index * 2], Line2 = tmpFilteredLines[(index * 2) + 1] }).ToList())).ToList()[0];
</test></test></test></test>
   
visit here...

Reading XML using LINQ[^]
   

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900