我有以下型号:
public class Input {
public Dictionary<String, String> A { get; set; }
public Dictionary<String, String> B { get; set; }
}
public class Output {
public String Key { get; set; }
public String A { get; set; }
public String B { get; set; }
}
我从服务中得到了以下信息:
List<Input> inputs = new List<Input> {
new Input {
A = new Dictionary<String, Int32> {
{ "EN", "Aen" },
{ "FR", "Afr" }
},
B = new Dictionary<String, Int32> {
{ "EN", "Ben" },
{ "FR", "Bfr" }
}
}
// More inputs ...
}
我需要将其映射到列表,如下所示:
List<Output> outputs = new List<Output> {
new Output { Key = "EN", A = "Aen", B = "Ben" },
new Output { Key = "FR", A = "Afr", B = "Bfr" }
}
我正在尝试以下操作:
var outputs = inputs
.Select(input => input.A.Select(a =>
new Output { Key = a.Key, A = a.Value ... })
问题是要创建输出,我需要A和B中的两个值。
答案 0 :(得分:1)
您似乎可以在此处使用Join
:
var ouputs = input.A.Join(
input.B,
a => a.Key,
b => b.Key,
(a, b) => new Output { Key = a.Key, A = a.Value, B = b.Value }
);
从性能的角度来看,如果您已经拥有索引数据,则可以使用更多代码来改善这一点。
var ouputs = input.A.Map(a => {
B b;
if(input.B.TryGetValue(a.Key, out b)) {
return {
Valid = true;
Output = new Output { Key = a.Key, A = a.Value, B = b.Value }
};
} else {
return { Valid = false, Output = null };
}
}).Where(result => result.Valid)
.Select(result => result.Output);
两者都是严格的内部联接。如果在没有对应关系的情况下需要A或B的数据,则情况会更加复杂。
答案 1 :(得分:0)
我假设A
和B
包含相同的key
集合。因此,input.A.Select
将遍历A
字典,并将为Key
类中的A
和Output
提供值。对于B
的值,我们可以直接使用input.B[a.Key]
获取,这将减少进一步的联接或复杂的操作。
但是它将提供List<List<Output>>
,所以我使用了inputs.SelectMany
,它将所有值合并到单个List<Output>
列表中。
var outputs = inputs.SelectMany(input => input.A.Select(
a => new Output
{
Key = a.Key,
A = a.Value,
B = input.B[a.Key]
});
答案 2 :(得分:0)
在没有您提供更多信息的情况下,我假设A和B可能具有不同的键。
为了匹配预期的结果,我使用SelectMany来修饰列表输出的列表。
var outputs = inputs
.SelectMany(input =>
input
.A.Keys // all key from A
.Union(input.B.Keys) // + all key from B without the duplicate
.Select(k =>
new Output
{
Key = k,
A = input.A.GetValueOrDefault(k),
B = input.B.GetValueOrDefault(k)
}
)
);
使用这种引出方法,:
public static TValue GetValueOrDefault<TKey, TValue>
(this IDictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue = default) =>
dictionary.TryGetValue(key, out var ret) ? ret : defaultValue;
答案 3 :(得分:0)
我将假设您的词典可能具有不同的键。
第一步-向您的Input
类添加属性,以返回两个字典使用的不同字典键:
public class Input
{
public Dictionary<string, string> A { get; set; }
public Dictionary<string, string> B { get; set; }
public IEnumerable<string> Keys
{
get
{
List<string> aKeys = A?.Keys.ToList() ?? new List<string>();
List<string> bKeys = B?.Keys.ToList() ?? new List<string>();
return aKeys.Union(bKeys);
}
}
}
第二步-创建将Input
对象转换为IEnumerable<Output>
的方法:
private static IEnumerable<Output> CreateOutput(Input input)
{
foreach (string key in input.Keys)
{
string aValue = null;
string bValue = null;
input.A?.TryGetValue(key, out aValue);
input.B?.TryGetValue(key, out bValue);
yield return new Output
{
A = aValue,
B = bValue,
Key = key
};
}
}
最后,使用SelectMany
将列表展平为一个列表:
List<Input> inputs = new List<Input>
{
new Input
{
A = new Dictionary<string, string>
{
{"EN", "Aen"},
{"FR", "Afr"},
{"PT", "PT value"}, // key does not exist in B dictionary
},
B = new Dictionary<string, string>
{
{"EN", "Ben"},
{"FR", "Bfr"},
{"DE", "DE value"}, // key does not exist in A dictionary
},
}
};
List<Output> outputs = inputs.SelectMany(CreateOutput).ToList();
输出:
答案 4 :(得分:0)
因为您没有指定其他方式,所以我假设:
input.A和input.B都不为空(但可以为空)
public List<Output> Flatten(Input input)
{
var outputs = new List<Output>();
foreach (var aKey in input.A.Keys)
{
//Check that input.B really has the key found in input.A
outputs.Add(new Output{Key = aKey, A = input.A[aKey], B = input.B.ContainsKey(aKey)? input.B[aKey]:null});
}
//If input.B has some keys not in input.A
foreach (var bKey in input.B.Keys)
{
//Check that the bKey was not already inserted (didn't exist earlier)
if (outputs.All(x => x.Key != bKey))
{
//A can be null.. it was not in the input.A
outputs.Add(new Output {Key = bKey, A = null, B = input.B[bKey]});
}
}
return outputs;
}
我会更好地将List重新定义为包含Key的字典以及包含字符串A和B的类,以便第二个循环更快。