2013-09-23 5 views
2

У меня есть входной файл, который включает данные о конферансье и их рейтинг производительности. Например,Невозможно заменить последний элемент в строке Список

1. Bill Monohan from North Town 10.54 
2. Mary Greenberg from Ohio 3.87 
3. Sean Hollen from Markell 7.22 

Я хочу, чтобы быть в состоянии взять последний номер из строки (их оценка), выполнить некоторые математические на нем, а затем заменить старые счеты с новым счетом. Вот краткий фрагмент кода, за то, что я пытаюсь сделать:

string line; 
StreamReader reader = new StreamReader(@"file.txt"); 

//Read each line and split by spaces into a List. 
while ((line = reader.ReadLine())!= null){ 

//Find last item in List and convert to a Double in order to perform calculations. 
    List<string> l = new List<string>(); 
    l = line.Split(null).ToList(); 
    string lastItem = line.Split(null).Last(); 
    Double newItem = Convert.ToDouble(lastItem); 

    /*Do some math*/ 
    /*Replace lastItem with newItem*/ 
    System.Console.WriteLine(line); } 

Когда я пишу новую строку, ничего не меняется, но я хочу lastItem переключаться с newItem в конце линии в настоящее время. Я пробовал использовать:

l[l.Length - 1] = newItem.ToString(); 

Но мне не повезло. Мне просто нужен лучший способ заменить последнее значение списка строк, как это. Я собираюсь на это в течение нескольких часов, и я почти в конце своей веревки. Помогите мне C# мастеров!

ответ

2

Вы можете использовать регулярные выражения MatchEvaluator, чтобы получить число из каждой строки, делать расчеты, и заменить оригинальный номер с новым:

string line = "1. Bill Monohan from North Town 10.54"; 
line = Regex.Replace(line, @"(\d+\.?\d*)$", m => { 
      decimal value = Decimal.Parse(m.Groups[1].Value); 
      value = value * 2; // calculation 
      return value.ToString(); 
     }); 

Это регулярное выражение захватывает десятичной число в конце строки ввода. Выход:

1. Bill Monohan from North Town 21.08 
0

Вы не меняете ничего на свой объект линии перед тем, как делать свою WriteLine.

Вам придется перестраивать свою линию, что-то вроде этого:

var items = string.Split(); 
items.Last() = "10";//Replace 
var line = string.Join(" ", items) 

Подсказка: строки являются неизменными, посмотрите его.

+0

Это не будет компилировать –

0

Это должно работать:

//var l = new List<string>(); // you don't need this 
var l = line.Split(null).ToList(); 
var lastItem = l.Last(); // line.Split(null).Last(); don't split twice 
var newItem = Convert.ToDouble(lastItem, CultureInfo.InvariantCulture); 
/*Do some math*/ 
/*Replace lastItem with newItem*/ 
l[l.Count - 1] = newItem.ToString(); // change the last element 
//Console.WriteLine(line); // line is the original string don't work 
Console.WriteLine(string.Join(" ", l)); // create new string 
0

Возможно, это сработает для вас. Слово при чтении файлов, если это возможно, то есть они вписываются в память, сразу считывает весь файл, он дает вам один доступ к диску (ну, в зависимости от размера файла, но да), и вам не нужно беспокоиться о дескрипторах файлов.

// Read the stuff from the file, gets an string[] 
    var lines = File.ReadAllLines(@"file.txt"); 

    foreach (var line in lines) 
    { 
     var splitLine = line.Split(' '); 
     var score = double.Parse(splitLine.Last(), CultureInfo.InvariantCulture); 

     // The math wizard is in town! 
     score = score + 3; 

     // Put it back 
     splitLine[splitLine.Count() - 1] = score.ToString(); 

     // newLine is the new line, what should we do with it? 
     var newLine = string.Join(" ", splitLine); 
     // Lets print it cause we are out of ideas! 
     Console.WriteLine(newLine); 
    } 

Что вы хотите сделать с конечным результатом? Вы хотите, чтобы это было записано в файл?

0

Попробуйте

string subjectString = "Sean Hollen from Markell 7.22"; 

    double Substring =double.Parse(subjectString.Substring(subjectString.IndexOf(Regex.Match(subjectString, @"\d+").Value), subjectString.Length - subjectString.IndexOf(Regex.Match(subjectString, @"\d+").Value)).ToString()); 

    double NewVal = Substring * 10; // Or any of your operation 

    subjectString = subjectString.Replace(Substring.ToString(), NewVal.ToString()); 

Примечание: Это не будет работать, если число появляется дважды на одной и той же линии

+1

Dangerous, что, если число в два раза по одной и той же линии?В вопросе конкретно указывается «последнее число» :) – flindeberg

+0

@flindeberg Спасибо, что указали, что вне – Rohit

0

Вы создаете и инициализации списка в цикле, следовательно, он содержит всегда только текущая строка. Вы хотите найти наивысший балл всех артистов или самый высокий балл каждого артиста (в случае, если артист может повторить в файле)?

Однако здесь подход, который дает вам обоим:

var allWithScore = File.ReadAllLines(path) 
    .Select(l => 
    { 
     var split = l.Split(); 
     string entertainer = string.Join(" ", split.Skip(1).Take(split.Length - 2)); 
     double score; 
     bool hasScore = double.TryParse(split.Last(), NumberStyles.Float, CultureInfo.InvariantCulture, out score); 
     return new { line = l, split, entertainer, hasScore, score }; 
    }) 
    .Where(x => x.hasScore); 
// highest score of all: 
double highestScore = allWithScore.Max(x => x.score); 
// entertainer with highest score 
var entertainerWithHighestScore = allWithScore 
    .OrderByDescending(x => x.score) 
    .GroupBy(x => x.entertainer) 
    .First(); 
foreach (var x in entertainerWithHighestScore) 
    Console.WriteLine("Entertainer:{0} Score:{1}", x.entertainer, x.score); 
// all entertainer's highest scores: 
var allEntertainersHighestScore = allWithScore 
    .GroupBy(x => x.entertainer) 
    .Select(g => g.OrderByDescending(x => x.score).First()); 
foreach (var x in allEntertainersHighestScore) 
    Console.WriteLine("Entertainer:{0} Score:{1}", x.entertainer, x.score); 
Смежные вопросы