C#在同一文本文件中组合行

时间:2010-11-18 18:28:07

标签: c#

我所拥有的文本文件是这样的:

apple|2  
turkey|4  
mango|11  
apple|3  
turkey|4  
mango|4  

我需要结果:

apple|5  
turkey|8  
mango|15  

任何提示或建议?我知道有一些Math.Abs​​等,我只是不确定如何组合这些线。任何帮助都会很棒。

8 个答案:

答案 0 :(得分:4)

File.WriteAllLines(
    "test.txt",
    File.ReadLines("test.txt")
        .Select(line => line.Split('|'))
        .Select(tokens => new
        {
            Value = int.Parse(tokens[1]),
            Text = tokens[0]
        })
        .GroupBy(li => li.Text)
        .Select(g => string.Format("{0}|{1}", g.Key, g.Sum(l => l.Value)))
        .ToArray()
);

或者如果您愿意:

File.WriteAllLines(
    "test.txt",
    (from lineItem in
        from line in File.ReadLines("test.txt")
        let tokens = line.Split('|')
        select new
        {
            Value = int.Parse(tokens[1]),
            Text = tokens[0]
        }
    group lineItem by lineItem.Text into g
    let sum = g.Sum(x => x.Value)
    select string.Format("{0}|{1}", g.Key, sum)).ToArray()
);

答案 1 :(得分:3)

未测试:

var lines = File.ReadLines(sourcePath);
var totals = lines.Select(line => line.Split('|'))
                  .Select(line => new { 
                      Item = line[0],
                      Count = Int32.Parse(line[1]) 
                  })
                  .GroupBy(x => x.Item)
                  .Select(g => new {
                      Item = g.Key,
                      Count = g.Sum(x => x.Count) 
                  });

File.WriteAllLines(
    destinationPath,
    totals.Select(total => String.Format("{0}|{1}", total.Item, total.Count)
);

你显然需要让它更强大,但我很确定这是一个。编译和b。产生预期的结果。

答案 2 :(得分:3)

LINQ解决方案很优雅,但是对于文本文件,我更喜欢一点错误检查。

string filePath = @"c:\temp\test.txt";
string line; 

Dictionary<string, int> dictAcculumator = new Dictionary<string,int>();

if (File.Exists( filePath ))
{
    using (StreamReader file = new StreamReader( filePath )){
        try
        {
            while ((line = file.ReadLine()) != null)
            {
                if (line.Contains('|')){
                    string[] items = line.Split('|');
                    int count;
                    string item = items[1];
                    if (int.TryParse(items[1], out count)){
                        if (dictAcculumator.ContainsKey(item)){
                            dictAcculumator[items[0]] += count;
                        }
                        else{
                            dictAcculumator.Add(items[0], count);
                        }
                    }
                }
            }
        }
        finally
        {
            if (file != null)
                file.Close();
        }
    } 
}

StringBuilder sb = new StringBuilder();
foreach (string key in dictAcculumator.Keys)
{
    //alternatively write to text file
    sb.AppendFormat("{0}|{1}\r\n", key, dictAcculumator[key].ToString());
}

Console.Write(sb.ToString());

答案 3 :(得分:2)

// read the text file
string[] wholeFile;
var values = new Dictionary<string, int>()
foreach (var line in lines)
{
    var pieces = line.Split('|');
    var name = pieces[0];
    var value = int.Parse(pieces[1]);
    if (!values.ContainsKey(name)
    {
        values[name] = 0;
    }

    values[name] = values[name] + value;
}
// spit it back out to a file.

我没有做文件IO也没有做错误检查,但这应该让你开始。

答案 4 :(得分:2)

创建Dictionary<string, int>。循环遍历文本文件的行,将行拆分为“|”。如果字符串没有字典条目,请创建一个。将数字添加到字典条目的值。完成循环遍历文本文件后,循环遍历字典并以所需格式输出结果。

答案 5 :(得分:1)

我确信在LINQ中有一个很好的方法可以做到这一点,但这样的事情会起作用。

string[] lines = File.ReadAllLines("myfile");

Dictionary<string, int> totals = new Dictionary<string, int>();
foreach (string line in lines)
{
  string[] fields = line.Split(new char[]{'|'});
  if (!totals.ContainsKey(fields[0]))
  {
    totals[fields[0]] = 0;
  }
  totals[fields[0]] += Convert.ToInt32(fields[1]);
}

foreach (KeyValuePair<string, int> total in totals)
{
  Console.WriteLine("{0}|{1}", total.Key, total.Value);
}

答案 6 :(得分:0)

您可以通过创建字典并迭代在元素存在时添加到值的行来完成此操作。我现在没有视觉工作室,所以在下面没有任何潜在的语法错误:

var linesInFile = File.ReadAllLines("c:\path\to\yourfile.txt");

var dict = new Dictionary<string, int>();

foreach(var line in linesInFile)
{
    var parts = string.Split(new char[] {'|'});
    var item = parts[0];
    var amount = int.Parse(parts[1]);
    if(dict.HasKey(item)){
        dict[item] += amount;
    }else{
        dict.Add(item, amount);
    }
}

foreach(var kvp in dict)
{
     Console.WriteLine(string.Format("{0}: {1}", kvp.Key, kvp.Value));
}

答案 7 :(得分:0)

以下是经过测试和运作的:

using System;
using System.Collections.Generic;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
    static void Main(string[] args)
    {
        List<Data> items = new List<Data>();
        using (StreamReader reader = new StreamReader("C:\\chedberg\\combine.txt"))
        {
            string line;
            string[] split;
            string name;
            int count;
            while (!reader.EndOfStream)
            {
                line = reader.ReadLine();
                if (!string.IsNullOrEmpty(line))
                {
                    split = line.Split('|');
                    name = split[0];
                    if(Int32.TryParse(split[1],out count))
                        items.Add(new Data() { Name = name, Count = count });
                }
            }

            List<Data> combinedItems = new List<Data>();
            items.ForEach(item =>
                              {
                                  if (!combinedItems.Exists(combinedItem => combinedItem.Name == item.Name)) 
                                      combinedItems.Add(new Data(){Name = item.Name, Count = item.Count});
                                  else
                                  {
                                      combinedItems.Find(combinedItem => combinedItem.Name == item.Name).Count += item.Count;
                                  }
                              });
            using (StreamWriter writer = new StreamWriter("C:\\chedberg\\combine_out.txt"))
            {
                combinedItems.ForEach(item => writer.WriteLine(String.Format("{0}|{1}",item.Name,item.Count)));
                writer.Flush();
            }
        }
    }

    public class Data
    {
        public string Name { get; set; }
        public int Count { get; set; }
    }
}

}