2013-09-23 47 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(); 

但我沒有運氣。我只需要最好的方法來替換像這樣的字符串List的最後一個值。我一直在這裏待了幾個小時,而我幾乎在我的繩索末端。 請幫我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

危險的,如果有什麼的次數爲兩次在同一行?這個問題明確指出「最後一個號碼」:) – 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); 
相關問題