2013-07-16 3 views
1

나는이LINQ의 접근 방식은/값

MyKey1=MyVal1 
MyKey2=MyVal2 
MyKey3=MyVal3 
MyKey3=MyVal3 

그래서 첫 번째 행으로 분할 할 필요, 나는 키를 얻기 위해 '='문자로 각 행을 분할해야 다음 문자열과 그 라인의 가치. 결과적으로 List<KeyValuePair<string, string>> (Dictionary? => 중복 키가있을 수 있음)이 표시되어 확장자 .ToDictionary()을 사용할 수 없습니다.

나는 다음과 같이 꽤 붙어있어 : 중복 키에 대한 우려된다면

List<KeyValuePair<string, string>> fields = 
    (from lines in Regex.Split(input, @"\r?\n|\r", RegexOptions.None) 
    where !String.IsNullOrWhiteSpace(lines) 
    .Select(x => x.Split(new [] { '='}, 2, StringSplitOptions.RemoveEmptyEntries)) 
    .ToList() 

    --> select new KeyValuePair? Or with 'let' for splitting by '='? 
     what about exception handling (e.g. ignoring empty values) 
+0

그룹을 원하십니까? 그렇게하면 특정 키에 대한 모든 값을 찾을 수 있습니다 ... 매우 쉽습니다. –

+1

그게 괴롭다. – Jonesopolis

답변

1

(I 예제를 일관성을 위해 모든 메소드 구문으로 변경했습니다.) :

List<KeyValuePair<string, string>> fields = 
    Regex.Split(input, @"\r?\n|\r", RegexOptions.None) 
    .Where(s => !String.IsNullOrWhiteSpace(s)) 
    .Select(x => x.Split(new [] {'='}, 2, StringSplitOptions.RemoveEmptyEntries) 
    .Where(p => p.Length == 2) // to avoid IndexOutOfRangeException 
    .Select(p => new KeyValuePair(p[0], p[1])); 

IEnumerable<IGrouping<string, string>> fields = 
    Regex.Split(input, @"\r?\n|\r", RegexOptions.None) 
    .Where(s => !String.IsNullOrWhiteSpace(s)) 
    .Select(x => x.Split(new [] {'='}, 2, StringSplitOptions.RemoveEmptyEntries)) 
    .GroupBy(p => p[0]); 
+0

'p.Length == 1' ??? 'IndexOutOfRangeException'을 작성하지 않았습니까? 또는 나는 오해가 무엇입니까? 이것은'p.Length == 2' 또는'p.Length> 1'이 아니어야합니까? – Alxandr

+0

@Alxandr 정답입니다. –

2

, 당신은 대신 ILookup 사용할 수 있습니다 : 당신은 아주 가까이있어

var fields = 
    (from line in Regex.Split(input, @"\r?\n|\r", RegexOptions.None) 
    select line.Split(new [] { '=' }, 2)) 
    .ToLookup(x => x[0], x => x[1]); 

var items = fields["MyKey3"]; // [ "MyVal3", "MyVal3" ] 
2

대신 사전의 Lookup<TKey, TValue>를 사용할 수 있습니다 :

var keyValLookup = text.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries) 
    .Select(l => 
    { 
     var keyVal = l.Split('='); 
     return new { Key = keyVal[0].Trim(), Value = keyVal.ElementAtOrDefault(1) }; 
    }) 
    .Where(x => x.Key.Length > 0) // not required, just to show how to handle invalid data 
    .ToLookup(x => x.Key, x => x.Value); 

IEnumerable<string> values = keyValLookup["MyKey3"]; 
Console.Write(string.Join(", ",values)); // MyVal3, MyVal3 

룩업 항상 심지어 키 경우 값을 반환 중복 키가있는 경우 그룹 청소기 될 것이라고 존의 의견에 REE 존재하지 않습니다. 그런 다음 빈 시퀀스입니다. 키는 고유하지 않아야하므로 ToLookup을 사용하기 전에 중복으로 그룹화하거나 제거 할 필요가 없습니다.

0

분할하는 대신 키/값을 일치시키는 것이 좋습니다. 당신이 키에 대해 여러 값과 사전도를 원한다면, 당신은 ToLookup (AN ILookup)를 사용할 수 있습니다

var result = Regex.Matches(input, @"(?<key>[^=\r\n]+)=(?<value>[^=\r\n]+)") 
        .OfType<Match>() 
        .ToLookup(m => m.Groups["key"].Value, 
          m => m.Groups["value"].Value); 

당신이 나중에 그 목록에 추가하거나 목록을 계속 사용하고자 할 경우 :

var result = Regex.Matches(input, @"(?<key>[^=\r\n]+)=(?<value>[^=\r\n]+)") 
        .OfType<Match>() 
        .Select(m => new KeyValuePair<string, string>(m.Groups["key"].Value, m.Groups["value"].Value)) 
        .ToList(); 

참고 : 사용자가 입력 한 내용을 모르기 때문에 사용 된 Regex가 용도에 적합하지 않을 수 있습니다.