C# 如何在列表和字典之间进行左连接?
我正在尝试将列表与字典相交,这非常有效:C# 如何在列表和字典之间进行左连接?,c#,.net,dictionary,functional-programming,visual-studio-2017,C#,.net,Dictionary,Functional Programming,Visual Studio 2017,我正在尝试将列表与字典相交,这非常有效: public static IDictionary<string, string> GetValues(IReadOnlyList<string> keys, IHeaderDictionary headers) { return keys.Intersect(headers.Keys) .Select(k => new KeyValuePair<string,
public static IDictionary<string, string> GetValues(IReadOnlyList<string> keys, IHeaderDictionary headers)
{
return keys.Intersect(headers.Keys)
.Select(k => new KeyValuePair<string, string>(k, headers[k]))
.ToDictionary(p => p.Key, p => p.Value);
}
然后我会期望结果是这样的:
[TestMethod]
public void GetValues_returns_dictionary_of_header_values()
{
var headers = new List<string> { { "trackingId" }, { "SourceParty" }, { "DestinationParty" } };
var trackingIdValue = "thisismytrackingid";
var sourcePartyValue = "thisismysourceparty";
var destinationPartyValue = "thisismydestinationparty";
var requestHeaders = new HeaderDictionary
{
{"trackingId", new Microsoft.Extensions.Primitives.StringValues(trackingIdValue) },
{"SourceParty", new Microsoft.Extensions.Primitives.StringValues(sourcePartyValue) },
{"DestinationParty", new Microsoft.Extensions.Primitives.StringValues(destinationPartyValue) },
{"randomHeader", new Microsoft.Extensions.Primitives.StringValues("dontcare") }
};
var headerValues = HeaderOperators.GetValues(headers, requestHeaders);
Assert.IsTrue(headerValues.ContainsKey("trackingId"));
Assert.IsTrue(headerValues.ContainsKey("SourceParty"));
Assert.IsTrue(headerValues.ContainsKey("DestinationParty"));
Assert.IsTrue(headerValues.Count == headers.Count);
}
var headerValues = HeaderOperators.GetValues(headers, requestHeaders, "myDefaultValue");
public static IDictionary<string, string> GetValues(IReadOnlyList<string> keys, IHeaderDictionary headers, string defaultValue)
{
return keys.GroupJoin(headers, key => key, header => header.Key, (key, header) => new { key, header })
.SelectMany(x => x.header.DefaultIfEmpty(), (x, header) => new { x.key, header.Value })
.Select(x => new KeyValuePair<string, string>(x.key, x.Value))
.ToDictionary(p => p.Key, p => p.Value ?? defaultValue);
}
其中headerValue
为:
{"trackingId", "thisismytrackingid"}
{"SourceParty", "thisismysourceparty"}
{"DestinationParty", "thisismydestinationparty"}
{"oneMoreKey", "myDefaultValue"}
如果交叉点不存在,如何向交叉点添加默认值?您可以在创建新词典时使用TryGetValue来填充默认值
public static IDictionary<string, string> GetValues(IReadOnlyList<string> keys, IHeaderDictionary headers, string defaultValue)
{
return keys.ToDictionary(k => k, k => headers.TryGetValue(k, out string val) ? val : defaultValue);
}
公共静态IDictionary getValue(IReadOnlyList键、IHeaderDictionary头、字符串defaultValue)
{
返回keys.ToDictionary(k=>k,k=>headers.TryGetValue(k,out string val)?val:defaultValue);
}
在GetValues函数中尝试以下Linq:
return keys.Intersect(headers.Keys)
.Select(k => new KeyValuePair<string, string>(k, headers[k]))
.Union(keys.Where(k => !headers.Keys.Contains(k)).Select(k => new KeyValuePair<string, string>(k, "myDefaultValue")))
.ToDictionary(p => p.Key, p => p.Value);
返回键.Intersect(headers.keys)
.Select(k=>newkeyvaluepair(k,headers[k]))
.Union(keys.Where(k=>!headers.keys.Contains(k))。选择(k=>newkeyvaluepair(k,“myDefaultValue”))
.ToDictionary(p=>p.Key,p=>p.Value);
它与在关键字列表中找不到的标题字典关键字中的任何值进行并集,并将这些值与默认值配对。基于此示例:您也可以使用GroupJoin
解决此问题,如下所示:
[TestMethod]
public void GetValues_returns_dictionary_of_header_values()
{
var headers = new List<string> { { "trackingId" }, { "SourceParty" }, { "DestinationParty" } };
var trackingIdValue = "thisismytrackingid";
var sourcePartyValue = "thisismysourceparty";
var destinationPartyValue = "thisismydestinationparty";
var requestHeaders = new HeaderDictionary
{
{"trackingId", new Microsoft.Extensions.Primitives.StringValues(trackingIdValue) },
{"SourceParty", new Microsoft.Extensions.Primitives.StringValues(sourcePartyValue) },
{"DestinationParty", new Microsoft.Extensions.Primitives.StringValues(destinationPartyValue) },
{"randomHeader", new Microsoft.Extensions.Primitives.StringValues("dontcare") }
};
var headerValues = HeaderOperators.GetValues(headers, requestHeaders);
Assert.IsTrue(headerValues.ContainsKey("trackingId"));
Assert.IsTrue(headerValues.ContainsKey("SourceParty"));
Assert.IsTrue(headerValues.ContainsKey("DestinationParty"));
Assert.IsTrue(headerValues.Count == headers.Count);
}
var headerValues = HeaderOperators.GetValues(headers, requestHeaders, "myDefaultValue");
public static IDictionary<string, string> GetValues(IReadOnlyList<string> keys, IHeaderDictionary headers, string defaultValue)
{
return keys.GroupJoin(headers, key => key, header => header.Key, (key, header) => new { key, header })
.SelectMany(x => x.header.DefaultIfEmpty(), (x, header) => new { x.key, header.Value })
.Select(x => new KeyValuePair<string, string>(x.key, x.Value))
.ToDictionary(p => p.Key, p => p.Value ?? defaultValue);
}
公共静态IDictionary getValue(IReadOnlyList键、IHeaderDictionary头、字符串defaultValue)
{
返回keys.GroupJoin(headers,key=>key,header=>header.key,(key,header)=>new{key,header})
.SelectMany(x=>x.header.DefaultIfEmpty(),(x,header)=>new{x.key,header.Value})
.选择(x=>newkeyvaluepair(x.key,x.Value))
.ToDictionary(p=>p.Key,p=>p.Value??defaultValue);
}
如果要从多个具有唯一值的其他列表创建列表,可以使用。您只需提供一个相等比较器,并确定如果两个源之间的值(对于同一个键)不同,该怎么办。谢谢!有没有办法进行不区分大小写的比较?我想进行交叉,但不关心casingYep-您必须按如下方式定义字典:var requestHeaders=new dictionary(StringComparer.OrdinalingOreCase),然后也按不区分大小写的方式进行交叉:keys.intersect(headers.keys,StringComparer.OrdinalingOreCase),谢谢!有没有办法进行不区分大小写的比较?我想交集,但不关心casingIt已经不区分大小写了,但是如果您想更改它,GroupJoin有一个IEqualityComparer比较器参数,所以您可以这样更改它:keys.GroupJoin(headers,key=>key,header=>header.key,(key,header)=>new{key,header},StringComparer.OrdinalIgnoreCase)