将具有重复值的集合拆分为范围,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();
}