Jump to content

Making an integer array from a text file

straight_stewie

So I need to read a text file with two digit integers arranged into a 20x20 grid, and put the numbers into an integer array 20x20. I have accomplished this but I'm just wondering if anyone has a better way to do this? The attached file is the one I need to read.

Here's the code I have (C#):

static void Main(string[] args)
        {
            
            string path = @"C:\MyFileLocation";
            string readGrid = File.ReadAllText(path).Replace("\n", "");
            char[] breakMeDown = readGrid.ToCharArray();

            int[,] numberGrid = GenerateArray(breakMeDown);
        }

        private static int[,] GenerateArray(char[] brokenDown)   //Return an integer array of the grid to be solved
        {
            int[,] gridHolder = new int[20, 20];
            int colIndex = 0;
            int rowIndex = 0;
            string temporary = null;

            foreach (char character in brokenDown)
            {
                temporary += character;

                if (temporary.Length == 3)
                {
                    temporary = temporary.Remove(2, 1);
                    gridHolder[rowIndex, colIndex] = Convert.ToInt32(temporary);
                    temporary = "";
                    colIndex++;

                }

                if (colIndex > 19)
                {
                    rowIndex++;
                    colIndex = 0;
                }
            }

            return gridHolder;

-P.S. If you know what this is for, please don't spoil it for me.

grid.txt

ENCRYPTION IS NOT A CRIME

Link to comment
Share on other sites

Link to post
Share on other sites

I'd suggest you use .Split :https://msdn.microsoft.com/en-us/library/tabh47cf%28v=vs.110%29.aspx
 

If you want compatibility with Linux, do a replace on the whole text file to remove the CR character .. ENTER is CR + LF   (0x0D + 0x0A), Linux often uses only LF to signify a new line.

Then, you can do split by "\n" or LF (depending) on your taste, then you can do a split by "," (edit: or space, just checked the text file) ... before converting to integer you may want to do Trim or check if it's actually a numeric value.

 

later edit . in c# , "\n"  is new line (LF , 0x0A) , "\r" is carriage return (CR, 0x0D):

Link to comment
Share on other sites

Link to post
Share on other sites

So the string.Split() method returns an array of strings with each row of the file being a string. I would still have to walk through the returned array to fix it. In my example the only reason I had to remove the \n character is because pressing "enter" on the keyboard generates an "\n\r" string, which messes up my "every third character" logic. 

ENCRYPTION IS NOT A CRIME

Link to comment
Share on other sites

Link to post
Share on other sites

Yeah, you initially split your file into an array of text lines.

Then, you can take lines one by one and split using a separator (space or comma or whatever) and you'll have an array with strings, each string being the number.

 

You do have to pay attention at the line delimiter, because for example if you have CR+LF and you split using LF initially, then every line in the array will have a CR character at the end. So, that should be removed - that's why I suggested running a  .Replace on the whole text file, replacing CR with nothing, to simplify your life. After that character is removed, you can simply split on the character LF.

 

By the way, you should really read the documentation, the File class has lots of methods that may simplify your life.. For example, there's File.ReadAllLines which reads the text file and returns an array of strings, one string for each line in the file. Basically, what you'd do with .Split in the first place and the method also takes care of those \n and \r issues properly, see the description here:  https://msdn.microsoft.com/en-us/library/bsy4fhsa%28v=vs.110%29.aspx

 

For the numbers in a line, you have something like this  (i don't have c# installed, i don't even code often in c#, this code probably is not valid but you should get the idea..

 

string[] lines = File.ReadAllLines(path);

line_counter = 0;

foreach (string line in lines) {

 string[] numbers = line.Split(" ");

 row_counter = 0;

 foreach (string s in numbers ) {

  if (!Int32.TryParse(s)) { // check if it's a number

    gridHolder[row_counter,line_counter] = Convert.ToInt32(s);

    row_counter++;

 }

 line_counter++;

}

 

 

 

 

Link to comment
Share on other sites

Link to post
Share on other sites

Here's a LINQ expression to do the whole thing (this assumes that a rectangular array is required):

const char delimiter = ' ';
var grid = File.ReadAllLines("grid.txt")
	.Select(line => line.Split(delimiter)
            .Select(v => int.Parse(v)).ToArray()).ToList().CreateRectangularArray();

And the extension method:

    public static class ListExtensions
    {
        public static T[,] CreateRectangularArray<T>(this IList<T[]> arrays)
        {
            var subLength = arrays[0].Length;
            var result = new T[arrays.Count, subLength];
            for (var i = 0; i < arrays.Count; i++)
            {
                var array = arrays[i];
                if (array.Length != subLength)
                {
                    throw new ArgumentException("All arrays must be the same length");
                }
                for (var j = 0; j < subLength; j++)
                {
                    result[i, j] = array[j];
                }
            }
            return result;
        }
    }

If you want a jagged array then:

const char delimiter = ' ';
var grid = File.ReadAllLines("grid.txt")
	.Select(line => line.Split(delimiter)
		.Select(v => int.Parse(v)).ToArray()).ToArray();

A better architecture would be to place all of this implementation detail behind an interface. If you have especially large data to process then you may consider exposing an IEnumarable on that interface and using yield whilst reading each line. If you have lots of data inconsistency then you should use something such as CsvHelper (no point trying to implement all of that checking yourself - it's been done before) since you can provide handlers and formatters for such situations in a clean architecture. If using a third party library one should always hide the implementation detail away behind an interface thus decoupling dependency.

 

Did you find out what this 'grid' is for yet?

The single biggest problem in communication is the illusion that it has taken place.

Link to comment
Share on other sites

Link to post
Share on other sites

 

Just now, Nuluvius said:

Did you find out what this 'grid' is for yet?

I can't spoil what this is for because it's for a problem solving website. That's why I came up with a solution that works before asking for better ways. 

ENCRYPTION IS NOT A CRIME

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×