我有一个输入文件,其中包含艺人的数据和他们的表现分数。例如,
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#大师!
答案 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);