LINQ 쿼리에서 NameValueCollection에 액세스 할 수 있도록 설정
NameValueCollection
where, join, groupby와 같은 LINQ 쿼리 연산자에 액세스 하는 방법은 무엇입니까?
나는 아래를 시도했다 :
private NameValueCollection RequestFields()
{
NameValueCollection nvc = new NameValueCollection()
{
{"emailOption: blah Blah", "true"},
{"emailOption: blah Blah2", "false"},
{"nothing", "false"},
{"nothinger", "true"}
};
return nvc;
}
public void GetSelectedEmail()
{
NameValueCollection nvc = RequestFields();
IQueryable queryable = nvc.AsQueryable();
}
그러나 나는 가지고 ArgumentException이 것을 말해 소스가되지는 IEnumerable <>입니다 .
비 제네릭 IEnumerable
을 IEnumerable<string>
. 사용을 제안 OfType
했지만 필터링 방법입니다. 당신이하는 일은 캐스트와 동등하며, Cast
연산자가 있습니다.
var fields = RequestFields().Cast<string>();
Frans가 지적했듯이 이것은 키에 대한 액세스 만 제공합니다. 값에 대한 컬렉션으로 인덱싱해야합니다. 다음은에서 KeyValuePair
s 를 추출하는 확장 방법입니다 NameValueCollection
.
public static IEnumerable<KeyValuePair<string, string>> ToPairs(this NameValueCollection collection)
{
if(collection == null)
{
throw new ArgumentNullException("collection");
}
return collection.Cast<string>().Select(key => new KeyValuePair<string, string>(key, collection[key]));
}
편집 : @Ruben Bartelink의 요청에 대한 응답으로 다음을 사용하여 각 키에 대한 전체 값 집합에 액세스하는 방법은 다음과 ToLookup
같습니다.
public static ILookup<string, string> ToLookup(this NameValueCollection collection)
{
if(collection == null)
{
throw new ArgumentNullException("collection");
}
var pairs =
from key in collection.Cast<String>()
from value in collection.GetValues(key)
select new { key, value };
return pairs.ToLookup(pair => pair.key, pair => pair.value);
}
또는 C # 7.0 튜플을 사용합니다.
public static IEnumerable<(String name, String value)> ToTuples(this NameValueCollection collection)
{
if(collection == null)
{
throw new ArgumentNullException("collection");
}
return
from key in collection.Cast<string>()
from value in collection.GetValues(key)
select (key, value);
}
AsQueryable
IEnumerable<T>
, 제네릭을 가져야합니다 . NameValueCollection
를 구현합니다 IEnumerable
.
대신 :
{
NameValueCollection nvc = RequestFields();
IQueryable queryable = nvc.AsQueryable();
}
Try OfType (일반이 아닌 인터페이스 허용)
{
NameValueCollection nvc = RequestFields();
IEnumerable<string> canBeQueried = nvc.OfType<string>();
IEnumerable<string> query =
canBeQueried.Where(s => s.StartsWith("abc"));
}
사전은 NameValueCollection이 채우는 역할을 실제로 더 많이 채울 것이기 때문에 실제로 사용하려는 것에 더 가깝습니다. 이것은 Bryan Watts의 솔루션의 변형입니다.
public static class CollectionExtensions
{
public static IDictionary<string, string> ToDictionary(this NameValueCollection source)
{
return source.Cast<string>().Select(s => new { Key = s, Value = source[s] }).ToDictionary(p => p.Key, p => p.Value);
}
}
나는 파티에 늦었지만 .Cast
확장 방법을 포함하지 않고 대신 AllKeys 속성을 사용하는 내 대답을 추가하고 싶었습니다 .
var fields = RequestFields().AllKeys;
이렇게하면 다음 확장 방법이 허용됩니다.
public static IEnumerable<KeyValuePair<string, string>> ToPairs(this NameValueCollection collection)
{
if(collection == null)
{
throw new ArgumentNullException("collection");
}
return collection.AllKeys.Select(key => new KeyValuePair<string, string>(key, collection[key]));
}
향후 방문자에게 도움이되기를 바랍니다.
The problem is that the collection implements IEnumerable
(as opposed to IEnumerable<T>
) and enumerating the collection returns the keys, not the pairs.
If I were you, I'd use a Dictionary<string, string>
which is enumerable and can be used with LINQ.
For me, @Bryan Watts' (+1'd) answer's ToLookup
variant represents by far the clearest approach for using it on a read-only basis.
For my use case, I'm manipulating a query string for use with Linq2Rest and also need to turn it all back into a NameValueCollection
at the end, so I have a set of extension methods for NameValueCollection
which offer more granular operations (to operate both per parameter name (AsEnumerable
) and per argument (AsKeyValuePairs
)) and also the inverse operation of converting it back ToNameValueCollection
(from either representation)).
Example consumption:
public static NameValueCollection WithoutPagingOperators( this NameValueCollection that )
{
return that.AsEnumerable()
.Where( @param => @param.Key != OdataParameters.Skip
&& @param.Key != OdataParameters.Top )
.ToNameValueCollection();
}
Code:
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
public static class NamedValueCollectionExtensions
{
public static IEnumerable<KeyValuePair<string, string[]>> AsEnumerable( this NameValueCollection that )
{
return that
.Cast<string>() // doesn't implement IEnumerable<T>, but does implement IEnumerable
.Select( ( item, index ) => // enable indexing by integer rather than string
new KeyValuePair<string, string[]>( item, that.GetValues( index ) ) ); // if you use the indexer or GetValue it flattens multiple values for a key, Joining them with a ',' which we don't want
}
public static IEnumerable<KeyValuePair<string, string>> AsKeyValuePairs( this IEnumerable<KeyValuePair<string, string[]>> that )
{
return that
.SelectMany( item =>
item.Value.Select( value =>
new KeyValuePair<string, string>( item.Key, value ) ) );
}
public static NameValueCollection ToNameValueCollection( this IEnumerable<KeyValuePair<string, string[]>> that )
{
return that.AsKeyValuePairs().ToNameValueCollection();
}
public static NameValueCollection ToNameValueCollection( this IEnumerable<KeyValuePair<string, string>> that )
{
var result = new NameValueCollection();
foreach ( KeyValuePair<string, string> item in that )
result.Add( item.Key, item.Value );
return result;
}
}
I don't really see why anyone would need to add an extension method.
Here's some different ways to do it in VB.NET. It includes 4 different intermediate forms of IEnumerable: Array, Tuple, Anonymous, and KeyValuePair. For the C# equivalent go to converter.telerik dot com and convert it.
Dim nvc As New NameValueCollection() From {{"E", "55"}, {"A", "11"}, {"D", "44"}, {"C", "33"}, {"G", "66"}, {"B", "22"}}
Dim dictStrings As Dictionary(Of String, String) = nvc.Cast(Of String).ToDictionary(Function(key) key, Function(key) nvc(key))
Dim Ints2Chars__ As Dictionary(Of Integer, Char) = nvc.Cast(Of Object).ToDictionary(Function(key) CInt(nvc(CStr(key))), Function(key) CChar(key))
Dim arrEnumerable__ = From x In nvc.Cast(Of String) Select {x, nvc(x)}
Dim tupleEnumerable = From x In nvc.Cast(Of String) Select Tuple.Create(x, nvc(x))
Dim anonEnumerable_ = From X In nvc.Cast(Of String) Select New With {X, .Y = nvc(X)}
Dim kvpEnumerable__ = From x In nvc.Cast(Of String) Select New KeyValuePair(Of String, String)(x, nvc(x))
Dim anonQuery = From anon In anonEnumerable_ Let n = CInt(anon.Y) Order By n Where n > 30 Select New With {.num = n, .val = anon.X}
Dim dictQuery = anonQuery.ToDictionary(Of Integer, String)(Function(o) o.num, Function(o) o.val)
Dim dictArray_ = arrEnumerable__.ToDictionary(Function(x) x(0), Function(x) x(1))
Dim dictTuples = tupleEnumerable.ToDictionary(Function(tuple) tuple.Item1, Function(tuple) tuple.Item2)
Dim dictAnon__ = anonEnumerable_.ToDictionary(Function(anon) anon.X, Function(anon) anon.Y)
Dim dictKVPrs_ = kvpEnumerable__.ToDictionary(Function(kvp) kvp.Key, Function(kvp) kvp.Value)
참고URL : https://stackoverflow.com/questions/391023/make-namevaluecollection-accessible-to-linq-query
'program tip' 카테고리의 다른 글
배경색에 따라 CSS 글꼴 색상 반전 (0) | 2020.12.04 |
---|---|
Python 목록에서 조건과 일치하는 처음 N 개 항목 제거 (0) | 2020.12.04 |
복합 색인은 어떻게 작동합니까? (0) | 2020.12.04 |
HTTP 다중 파트 (POST) 요청의 경계 매개 변수는 무엇입니까? (0) | 2020.12.04 |
onkeydown 이벤트에서 백 스페이스를 캡처하는 방법 (0) | 2020.12.04 |