无法替换字符串List中的最后一个元素

时间:2013-09-23 08:48:08

标签: c# list

我有一个输入文件,其中包含艺人的数据和他们的表现分数。例如,

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); }

当我写新行时,没有任何变化,但我希望现在可以在行尾使用newItem切换lastItem。我尝试过使用:

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

但我没有运气。我只需要最好的方法来替换像这样的字符串List的最后一个值。我已经在这里待了几个小时了,我几乎就在绳子的尽头。 请帮帮我c#大师!

6 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

在进行WriteLine之前,您不会更改任何内容。

你必须重建你的行,如下所示:

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

提示:字符串是不可变的,查找它。

答案 2 :(得分: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

答案 3 :(得分: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);
  }

你想对最终结果做什么?你想把它写回文件吗?

答案 4 :(得分: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());

注意:如果数字在同一行显示两次

,则无效

答案 5 :(得分: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);