将具有重复值的集合拆分为范围,C#
Split a collection with repeated values into ranges, C#
我有两个列表:
List<string> keys = new List<string>()
{
"REPORTMONTH",
"CONTRACT", "DATE", "AMOUNT",
"CONTRACT", "DATE", "AMOUNT"
};
List<string> values = new List<string>()
{
"01",
"ABC123", "01022014", "300.00",
"DEF345", "03042014", "400.00"
};
第一个列表代表可以有一定重复的关键词。第二个列表包含与第一个列表中的键关联的值(按索引)。结果输出应该是 List<Dictionary<string, string>>
类型并且包含:
1st dictionary
key value
"REPORTMONTH" "01"
"CONTRACT" "ABC123"
"DATE" "01022014"
"AMOUNT" "300.00"
2nd dictionary
key value
"REPORTMONTH" "01"
"CONTRACT" "DEF345"
"DATE" "03042014"
"AMOUNT" "400.00"
即不重复的键应该出现在两个字典中,其余的应该分成具有关联值的字典。
注意,不能完全没有重复,也不能超过 2 次。
抱歉,我无法展示我对这个问题的尝试,因为我不确定如何开始。也许使用 LINQ 和分组可以解决问题?
谢谢。
您可以先使用 Enumerable.Zip()
获取 key/value 对序列并将列表转换为 lookup
,然后将该列表处理成两个字典:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication2
{
class Program
{
static void Main()
{
List<string> keys = new List<string>
{
"REPORTMONTH",
"CONTRACT", "DATE", "AMOUNT",
"CONTRACT", "DATE", "AMOUNT"
};
List<string> values = new List<string>
{
"01",
"ABC123", "01022014", "300.00",
"DEF345", "03042014", "400.00"
};
var combined = Enumerable.Zip(
keys, values, (key, value) => new { Key = key, Value = value})
.ToLookup(entry => entry.Key);
var dicts = new []
{
new Dictionary<string, string>(),
new Dictionary<string, string>()
};
foreach (var items in combined)
{
int count = 0;
string lastKey = null;
foreach (var item in items.Take(2))
{
dicts[count++][item.Key] = item.Value;
lastKey = item.Key;
}
if (count == 1)
dicts[1][lastKey] = dicts[0][lastKey];
}
dump("1st dictionary", dicts[0]);
dump("2nd dictionary", dicts[1]);
}
static void dump(string title, Dictionary<string, string> data)
{
Console.WriteLine(title);
foreach (var item in data)
Console.WriteLine("Key: {0}, Value: {1}", item.Key, item.Value);
Console.WriteLine();
}
}
}
你可以用一种看起来不太优雅的方式来做这件事,需要一些循环。请注意,如果有超过 2 个词典,这也将起作用。
public static void Main(params string[] args)
{
List<string> keys = new List<string>() {
"REPORTMONTH",
"CONTRACT", "DATE", "AMOUNT",
"CONTRACT", "DATE", "AMOUNT"
};
List<string> values = new List<string>() {
"01",
"ABC123", "01022014", "300.00",
"DEF345", "03042014", "400.00"
};
var pairs = keys.Select((key, ndx) => new { Key = key, Value = values[ndx] });
var groups = pairs.GroupBy(e => e.Key)
.ToDictionary(g => g.Key, g => g.Select(kvp => kvp.Value).ToArray());
var dictionaries = new Dictionary<string, string>[groups.Max(g => g.Value.Length)];
for (var i = 0; i < dictionaries.Length; i++)
{
dictionaries[i] = new Dictionary<string,string>();
foreach (var g in groups)
{
if (g.Value.Length == 1)
dictionaries[i][g.Key] = g.Value[0];
else if (g.Value.Length > i)
dictionaries[i][g.Key] = g.Value[i];
}
}
// print content
for (var i = 0; i < dictionaries.Length; i++)
{
Console.WriteLine("Dictionary {0}:", i + 1);
Console.WriteLine(string.Join(Environment.NewLine, dictionaries[i].Select(e => string.Format("{0} = {1}", e.Key, e.Value))));
Console.WriteLine();
}
Console.ReadLine();
}
我有两个列表:
List<string> keys = new List<string>()
{
"REPORTMONTH",
"CONTRACT", "DATE", "AMOUNT",
"CONTRACT", "DATE", "AMOUNT"
};
List<string> values = new List<string>()
{
"01",
"ABC123", "01022014", "300.00",
"DEF345", "03042014", "400.00"
};
第一个列表代表可以有一定重复的关键词。第二个列表包含与第一个列表中的键关联的值(按索引)。结果输出应该是 List<Dictionary<string, string>>
类型并且包含:
1st dictionary
key value
"REPORTMONTH" "01"
"CONTRACT" "ABC123"
"DATE" "01022014"
"AMOUNT" "300.00"
2nd dictionary
key value
"REPORTMONTH" "01"
"CONTRACT" "DEF345"
"DATE" "03042014"
"AMOUNT" "400.00"
即不重复的键应该出现在两个字典中,其余的应该分成具有关联值的字典。 注意,不能完全没有重复,也不能超过 2 次。
抱歉,我无法展示我对这个问题的尝试,因为我不确定如何开始。也许使用 LINQ 和分组可以解决问题?
谢谢。
您可以先使用 Enumerable.Zip()
获取 key/value 对序列并将列表转换为 lookup
,然后将该列表处理成两个字典:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication2
{
class Program
{
static void Main()
{
List<string> keys = new List<string>
{
"REPORTMONTH",
"CONTRACT", "DATE", "AMOUNT",
"CONTRACT", "DATE", "AMOUNT"
};
List<string> values = new List<string>
{
"01",
"ABC123", "01022014", "300.00",
"DEF345", "03042014", "400.00"
};
var combined = Enumerable.Zip(
keys, values, (key, value) => new { Key = key, Value = value})
.ToLookup(entry => entry.Key);
var dicts = new []
{
new Dictionary<string, string>(),
new Dictionary<string, string>()
};
foreach (var items in combined)
{
int count = 0;
string lastKey = null;
foreach (var item in items.Take(2))
{
dicts[count++][item.Key] = item.Value;
lastKey = item.Key;
}
if (count == 1)
dicts[1][lastKey] = dicts[0][lastKey];
}
dump("1st dictionary", dicts[0]);
dump("2nd dictionary", dicts[1]);
}
static void dump(string title, Dictionary<string, string> data)
{
Console.WriteLine(title);
foreach (var item in data)
Console.WriteLine("Key: {0}, Value: {1}", item.Key, item.Value);
Console.WriteLine();
}
}
}
你可以用一种看起来不太优雅的方式来做这件事,需要一些循环。请注意,如果有超过 2 个词典,这也将起作用。
public static void Main(params string[] args)
{
List<string> keys = new List<string>() {
"REPORTMONTH",
"CONTRACT", "DATE", "AMOUNT",
"CONTRACT", "DATE", "AMOUNT"
};
List<string> values = new List<string>() {
"01",
"ABC123", "01022014", "300.00",
"DEF345", "03042014", "400.00"
};
var pairs = keys.Select((key, ndx) => new { Key = key, Value = values[ndx] });
var groups = pairs.GroupBy(e => e.Key)
.ToDictionary(g => g.Key, g => g.Select(kvp => kvp.Value).ToArray());
var dictionaries = new Dictionary<string, string>[groups.Max(g => g.Value.Length)];
for (var i = 0; i < dictionaries.Length; i++)
{
dictionaries[i] = new Dictionary<string,string>();
foreach (var g in groups)
{
if (g.Value.Length == 1)
dictionaries[i][g.Key] = g.Value[0];
else if (g.Value.Length > i)
dictionaries[i][g.Key] = g.Value[i];
}
}
// print content
for (var i = 0; i < dictionaries.Length; i++)
{
Console.WriteLine("Dictionary {0}:", i + 1);
Console.WriteLine(string.Join(Environment.NewLine, dictionaries[i].Select(e => string.Format("{0} = {1}", e.Key, e.Value))));
Console.WriteLine();
}
Console.ReadLine();
}