Writing the Contents of KeyValuePair List to Text Files - with a catch
What is the optimal way to write the "Values" available in a List to a Text file? The catch is the Text file's name should be determined by the Key.
For example, I managed to construct a List like开发者_C百科 this:
["Animal", "Lion|Roars"]
["Animal", "Tiger|Roars"]
["Bird", "Eagle|Flies"]
["Bird", "Parrot|Mimics"]
We need to write two files based on the above: Animal.txt and Bird.txt each containing their respective values only.
What is an efficient way to do this?
Thank you SOF community.
I would use LINQ to do the grouping, then write each group to a file at once. Something as simple as this should do it:
static void WriteFiles(IEnumerable<KeyValuePair<string, string>> data)
{
foreach (var group in from kvp in data
group kvp.Value by kvp.Key)
File.WriteAllLines(group.Key + ".txt", group);
}
foreach (var group in yourList.GroupBy(x => x.Key, x => x.Value))
{
File.WriteAllLines(group.Key + ".txt", group);
}
You may try grouping:
class Program
{
static void Main()
{
var data = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("Animal", "Lion|Roars"),
new KeyValuePair<string, string>("Animal", "Tiger|Roars"),
new KeyValuePair<string, string>("Bird", "Eagle|Flies"),
new KeyValuePair<string, string>("Bird", "Parrot|Mimics")
};
var groups = data.GroupBy(x => x.Key);
foreach (var group in groups)
{
var filename = Path.ChangeExtension(group.Key, "txt");
var content = string.Join(Environment.NewLine, group.Select(x => x.Value));
File.WriteAllText(filename, content);
}
}
}
which would generate:
Animal.txt
:Lion|Roars Tiger|Roars
Bird.txt
:Eagle|Flies Parrot|Mimics
You do not need to try to linqify everything. When you create a grouping you create from all data in the list a dictionary before you can write a single line to the output. This will consume at least twice as much memory as it is necessary. This design eliminates lazy processing since you are eagerly reading everything into memory before you can write output.
Instead you can process the list one by one and write to the current line to the right file. This can be as easy as a hash table lookup for the right file stream by using Animal or Bird as keys to choose the right output file.
static Dictionary<string, StreamWriter> _FileMap = new Dictionary<string, StreamWriter>();
static void Main(string[] args)
{
var data = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("Animal", "Lion|Roars"),
new KeyValuePair<string, string>("Animal", "Tiger|Roars"),
new KeyValuePair<string, string>("Bird", "Eagle|Flies"),
new KeyValuePair<string, string>("Bird", "Parrot|Mimics")
};
foreach (var line in data) // write data to right output file
{
WriteLine(line.Key, line.Value);
}
foreach (var stream in _FileMap) // close all open files
{
stream.Value.Close();
}
}
static void WriteLine(string key, string line)
{
StreamWriter writer = null;
if (false == _FileMap.TryGetValue(key, out writer))
{
// Create file if it was not opened already
writer = new StreamWriter(File.Create(key+".txt"));
_FileMap.Add(key,writer);
}
writer.WriteLine(line); // write dynamically to the right output file depending on passed key
}
So you have
List<KeyValuePair<string, string>> keyValuePairs;
and you want to write these to a file, based on the Key
property for each pair. Fine, just group by the Key
and append to the filename based on the Key
.
var groups = keyValuePairs.GroupBy(x => x.Key);
foreach(var group in groups) {
File.AppendAllLines(
GetFilenameFromKey(group.Key),
group.Select(x => x.Value)
);
}
Here, a naive version of GetFilenameFromKey
is
public string GetFilenameFromKey(string key) {
return Path.ChangeExtension(key, "txt");
}
精彩评论