2010-08-20 3 views
1

У меня есть матрица в этом формате, который я пытаюсь проверить и удалить первую строку:Пропустить первую строку в матрице, и проверка ширины/высоты

3 4 
0 0 0 
0 0 0 
0 0 0 
0 0 0 

Если первая линия и другие линии фактические данные.

Width Height 

Что такое лучший способ A Удалите первый ряд, и B проверьте, что все строки соответствуют Ширина Критерии Высота указано? Я мог бы сделать простой цикл и скопировать их, но я ищу более элегантный способ сделать это? Может быть, с Linq или одним из методов сбора?

До сих пор у меня есть:

//add the split for correctness 
string[][] lines = File.ReadAllLines(fileName).Select(x=>x.Split(' ')).ToArray(); 
//first line is width/hight 
int length = lines.Length ==0 ; 
if(|| (length > 0 && lines[0].Length !=2)){ 
    throw new InvalidDataException("File is not correctly formated:" + fileName); 
} 

int width = lines[0][0]; 
int hieght = lines[0][1]; 

//Check Row count  
if(length != height -1){ 
    throw new InvalidDataException("Invalid missing rows in the Matrix definition"); 
} 

//make sure the file is correctly formated with width and height:  
if(lines.Any(x=>x.Length != Width)){ 
    //I know this fails because of first line 
    throw new InvalidDataException("Invalid Width in a row in the Matrix"); 
} 

Все предложения на лучший способ подтвердить ввод?

ответ

1

sscanf было бы хорошо, но я сделал это с рег. эксп. и она будет проверить, является ли ширина и высота целые числа, а также проверяет каждый следующий номер для того, чтобы быть целым числом:

static bool isValid(string path) 
{ 
    var data = File.ReadAllText(path); 

    var first = Regex.Match(data, @"\A *(\d+) +(\d+) *([\r\n|\n]|\Z)"); 

    if (!first.Success) return false; 

    int width = int.Parse(first.Groups[1].Value); 
    int height = int.Parse(first.Groups[2].Value); 

    return Regex.Match(data, @"\A *\d+ +\d+ *((\r\n|\n)((^ *| +)\d+){" + width + @"} *){" + height + @"}\Z", RegexOptions.Multiline).Success; 
} 

я могу сделать его более строгим в отношении пространств.

Добавлен:

Если вы хотите сохранить все строки, кроме первой, на новый путь, то это будет делать:

var lines = File.ReadLines(path); 
File.WriteLines(path2, lines.Skip(1)); 

Или, если вы просто хотите массив линии, за исключением первых, используйте это:

var linesExceptFirst = File.ReadLines(path).Skip(1); 
+0

Dont также необходимо добавить в регулярное выражение, что первая строка является размер 2? (или я пропустил это?) – Nix

+0

Они всегда будут intergers ... 0 1 2 3 – Nix

+0

@Nix '\ d +' есть дважды. Поэтому он будет принят только в том случае, если они являются целыми числами. –

0

Я бы потянул его в виде двух отдельных массивов.

using(StreamReader sr = new StreamReader(fileName) 
{ 
    string header[] = sr.ReadLine().Split(' '); 
    if(header.Length != 2) throw new InvalidDataException("yadda, yadda"); 

    List<string> lines = new List<string>(); 
    //you'll probably want to move that declaration outside the using statement... 

    while(sr.Peek() != -1) 
    { 
    lines.Add(sr.ReadLine()); 
    } 

    if(lines.Count() != int.Parse(header[1])) //this is wrong so... 
    throw new InvalidDataException("yadda, yadda"); 

    if(lines.AsQueryable().Any(x => x.length != int.Parse(header[0]))// this, too 
    throw new InvalidDataException("yadda, yadda"); 
} 

Проблема в том, что ваши данные образца имеют пробелы, и этот код не допускает пробелов в данных. Таким образом, мы должны исправить ...

List<string[]> separatedLines = new List<string[]>(); 

lines.ForEach(x => separatedLines.Add(x.Split(' '))); 

if(separatedLines.AsQueryable().Any(s => s.Length != int.Parse(header[0]))) 
    throw new InvalidDataException("yadda, yadda"); 

Некоторые, что изменятся, если я неправильно понял ваши данные примеров, но это будет ваша строка заголовка первой, и использовать его значение для проверки остальной части ваших данных , Дважды проверьте меня на звонках .AsQueryable(), хотя у меня не так много шансов использовать Linq, как хотелось бы, поэтому я имею относительно ограниченный опыт в этом. Я знаю, что, когда я пытался, используя методы Linq добавочным Список принимает некоторые незначительные акробатики ...

2
string[][] lines = File.ReadAllLines(fileName) 
    .Select(line => line.Split(' ')).ToArray(); 
if (lines[0].Length != 2) 
    throw new SomeException(); 

int width = int.Parse(lines[0][0]); 
int height = int.Parse(lines[0][1]); 

int[][] matrix = lines.Skip(1) 
    .Select(line => line.Select(n => int.Parse(n)).ToArray()) 
    .ToArray(); 

if (matrix.Length != height || matrix.Any(line => line.Length != width)) 
    throw new SomeException(); 
+0

Очень элегантный - но немного хрупкий - рассмотрим случай, когда два элемента разделены несколькими пробелами - возможно, требуется шаг препроцесса, который избавляется от многопроцессорных запусков. Кроме того, вы можете, конечно, отказаться от инициализатора высоты и просто использовать функцию в последней line - может быть, и ширина, но я не знаю, будет ли ilm распознавать ее как постоянную или пересчитать ее на каждый предмет. Но, тем не менее, элегантный –

Смежные вопросы