Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从C中缺少键的列表创建完整集_C#_.net_Linq_Arraylist_Key Value - Fatal编程技术网

C# 从C中缺少键的列表创建完整集

C# 从C中缺少键的列表创建完整集,c#,.net,linq,arraylist,key-value,C#,.net,Linq,Arraylist,Key Value,我做了很多挖掘工作,似乎找不到这个问题的答案;类似问题的答案,但不是这样的 本质上,我要做的是在列表中添加带有默认值的缺少的键。我有一个结构如下的列表: 关键词:价值 从上面的列表中,我想创建一个完整的集合,其中包含缺少的键。 预期键:值 我正在尝试以下代码: var list = new List<KeyValuePair<string, string>> { new KeyValuePair<string, string>("n

我做了很多挖掘工作,似乎找不到这个问题的答案;类似问题的答案,但不是这样的

本质上,我要做的是在列表中添加带有默认值的缺少的键。我有一个结构如下的列表:

关键词:价值 从上面的列表中,我想创建一个完整的集合,其中包含缺少的键。

预期键:值 我正在尝试以下代码:

var list = new List<KeyValuePair<string, string>>
{
        new KeyValuePair<string, string>("name", "Orange"),
        new KeyValuePair<string, string>("actualname", "Orango"),
        new KeyValuePair<string, string>("name", "Lime"),
        new KeyValuePair<string, string>("fullname", "Lime Lime"),
        new KeyValuePair<string, string>("actualname", "Limo")
};
var distinctKeys = list
    .Select(pair => pair.Key)
    .Distinct()
    .OrderBy(pair => pair)
    .ToArray();
var lastKeyIndex = -1;

for (var index = 0; index < list.Count; index++)
{
    var currentKeyIndex = lastKeyIndex + 1 == distinctKeys.Length ? 0 : lastKeyIndex + 1;
    var currentKey = distinctKeys[currentKeyIndex];

    if (list[index].Key != currentKey)
    {
        list.Insert(index, new KeyValuePair<string, string>(currentKey, string.Empty));
    }

    lastKeyIndex = currentKeyIndex;
}

for (var index = lastKeyIndex+1; index < distinctKeys.Length; index++)
{
    list.Add(new KeyValuePair<string, string>(distinctKeys[index], string.Empty));
}
预期产量

预期键:值
我们欢迎任何想法来解决这个问题。

给定每个分组的第一个键,您可以对其进行分组,您可以创建一个完整的键列表,按每组的偏序排序,然后扩展每个组以获得完整的键集

首先,IEnumerable上的一些扩展允许您在谓词上分组,当每个组为true时,从每个组开始,一个用于DistinctBy:

现在,您可以根据关键帧在每个集中的显示位置创建关键帧的偏序,然后对不同的关键帧进行排序:

var ordering = list.GroupByUntil(kvp => kvp.Key == firstKey)
                   .OrderBy(g => g.Count())
                   .SelectMany((g,sn) => g.Select((g, n) => new { g.Key, n = (sn+1)*n }))
                   .OrderBy(kn => kn.n)
                   .DistinctBy(kn => kn.Key, g => g.Last())
                   .ToDictionary(kn => kn.Key, kn => kn.n);
var keySet = list.Select(kvp => kvp.Key).Distinct().OrderBy(k => ordering[k]).ToList();
使用键集,可以展开每组项以拥有所有键:

var ans = list.GroupByUntil(kvp => kvp.Key == firstKey)
              .Select(g => g.ToDictionary(l => l.Key, l => l.Value))
              .SelectMany(d => keySet.Select(k => new KeyValuePair<string, string>(k, d.TryGetValue(k, out var v) ? v : "")));

如果你喜欢把最终集仍然分组,只要用SLECT.

替换SCONTUME建议:考虑使用A,或者类似字典。PaulSM4尝试过了,没有工作。你能相应地更新代码吗?@SM4号。。你不会在这里使用字典,你不需要唯一的键@DaemonBee,数据实际上是一个文本文件;您是从流中获取数据,还是在此列表表示之前从字符串[]或字符串开始获取数据?您是否已经确切地知道在此序列\集中将使用哪些键\属性?通常,我不知道如何从数据集中提取所需的最终关键点,因为对关键点进行排序可能会放弃集合排序-想象一下,如果第一个集合没有contacts.coid-您如何知道以下contacts.coid启动了一个新集合?问题是,我看不到自动检测集合之间边界的方法设置原始列表。如果我们遵循顺序,那么对于第一个集合只有contacts.coid值而第二个集合只有createdon值的情况,那么我们如何能够自动判断这两个值属于不同的集合。对于一个完整集合,没有按正确顺序排列的完整键列表。它只能从给定的列表中动态派生。@DaemonBee通常,当任何键可能丢失时,无法派生完整的键列表。没有可以用来区分部分关键点集的标记。如果你愿意接受这个限制,或者应用另一个约束,比如键总是按字母顺序排列,这可能会有所不同。你是对的。第一列是必填的。假设第一列始终存在,是否可以这样做。@DaemonBee是的,但请注意,您的第二个示例缺少第一列。该集合已更正,以反映第一列为必填项
contacts.coid : 2003984
createdon : 2020-09-10
c_id : fcd5937d
contacts.coid : 2024489
createdon : 2020-09-10
contacts.fullname : Mark
contacts.coid : 99
c_id : 7e70096e
contacts.coid : 2024496
createdon : 2020-09-10
contacts.fullname : Simon
c_id : ebbbd1f4
contacts.coid : 2003984
createdon : 2020-09-10
contacts.fullname : ""
c_id : fcd5937d
contacts.coid : 2024489 
createdon : 2020-09-10
contacts.fullname : Mark
c_id : ""
contacts.coid : 99
createdon : ""
contacts.fullname : ""
c_id : 7e70096e
contacts.coid : 2024496
createdon : 2020-09-10
contacts.fullname : Simon
c_id : ebbbd1f4
public static class IEnumerableExt {
    // TRes seedFn(T FirstValue)
    // TRes combineFn(TRes PrevResult, T CurValue)
    // Based on APL scan operator
    // Returns TRes
    public static IEnumerable<TRes> Scan<T, TRes>(this IEnumerable<T> items, Func<T, TRes> seedFn, Func<TRes, T, TRes> combineFn) {
        using (var itemsEnum = items.GetEnumerator()) {
            if (itemsEnum.MoveNext()) {
                var prev = seedFn(itemsEnum.Current);

                while (itemsEnum.MoveNext()) {
                    yield return prev;
                    prev = combineFn(prev, itemsEnum.Current);
                }
                yield return prev;
            }
        }
    }

    // returns groups of T items each starting when testFn is true
    public static IEnumerable<IEnumerable<T>> GroupByUntil<T>(this IEnumerable<T> items, Func<T, bool> testFn) =>
        items.Scan(item => (groupNum: 0, theItem: item), (a, item) => testFn(item) ? (a.Item1+1, item) : (a.Item1, item))
             .GroupBy(t => t.groupNum)
             .Select(tg => tg.Select(t => t.theItem));

    // returns a single item from each group of items by keyFn(item) picked by pickFn(itemGroup)
    public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> items, Func<T, TKey> keyFn, Func<IGrouping<TKey, T>, T> pickFn, IEqualityComparer<TKey> comparer = null) =>
        items.GroupBy(keyFn, comparer).Select(pickFn);
}
var firstKey = "name";
var ordering = list.GroupByUntil(kvp => kvp.Key == firstKey)
                   .OrderBy(g => g.Count())
                   .SelectMany((g,sn) => g.Select((g, n) => new { g.Key, n = (sn+1)*n }))
                   .OrderBy(kn => kn.n)
                   .DistinctBy(kn => kn.Key, g => g.Last())
                   .ToDictionary(kn => kn.Key, kn => kn.n);
var keySet = list.Select(kvp => kvp.Key).Distinct().OrderBy(k => ordering[k]).ToList();
var ans = list.GroupByUntil(kvp => kvp.Key == firstKey)
              .Select(g => g.ToDictionary(l => l.Key, l => l.Value))
              .SelectMany(d => keySet.Select(k => new KeyValuePair<string, string>(k, d.TryGetValue(k, out var v) ? v : "")));