2009-11-03 6 views
4
이 아주 쉽게 할 무언가를해야처럼이 보인다

통해 반복하면서 "미리 엿보기",하지만 난이 문제를 접근 할 때마다, 나는/w를 느낄 여기에 '덜 우아한보다는 "사전 항목

솔루션을 끝낼 내 기본적인 질문입니다 : 내가 특정 방식으로 주문한 사전을 통해 반복한다면, 루프의 특정 지점 내에서 사전 항목 'x'를 참조하거나 현재 항목보다 먼저 참조 할 수 있습니까? 현재 열거자를 바꾸지 않고? 예 :

Dim tempDictionary = New Dictionary(Of String, String) 

tempDictionary.Add("TestName1", "TestValue1") 
tempDictionary.Add("TestName2", "TestValue2") 
tempDictionary.Add("TestName3", "TestValue3") 
'... and so on ... ' 

For Each Item In tempDictionary 
DoStuff(Item) 

'Here is the point in which I want to see what the value of the' 
'dictionary item that is 1, 2, 3, [x] places in front of the current' 
'item without interfering w/ the current loop.' 

'CODE' 

Next 

미리 감사드립니다.

답변

1

C 스타일의 루프를 원한다는 소리가 들립니다. (당신이 VB에서 질문 때문에)

언급 한 바와 같이
for (int i = 0; i < myArray.Length; i++) { 
    object current = myArray[i]; 

    if(i + 1 < myArray.Length) { // make sure there is a next item 
     object nextItem = myArray[i + 1] 
    } 
} 

가하는 사전을 주문하지 않습니다 여기에 C#을 용서하지만 위의를 사용하여 배열에 키를 넣어 수 있습니다.

+0

좋은 접근 방법입니다. 색인이있는 키를 사용하여 2 차 모음을 만들어야하지만 그 방법은 경량이지만 여전히 제네릭을 유지할 수 있습니다. – Nathan

4

Dictionary은 정렬 된 데이터 구조가 아닙니다. 사전에 열거 된 항목의 순서에 의존 할 수 없습니다. 항목을 순서대로 정렬해야하는 경우 일반 List을 사용하거나 제 3 자 주문 사전 (예 : Wintellect's Power Collections)을 사용해야합니다.

사실 실제로 System.Collections.Specialized에는 OrderedDictionary이 있지만 일반적이지는 않습니다.

일반적인 맞춤 주문 사전을 만들려면 this CodeProject article이 (가) 관심을 가질 수 있습니다.

+0

나는 Ordered Dictionary 방식을 좋아하고 그것을 생각하지 않았습니다. 나는 이중 점검을 할 것이지만, 일반적인 측면이 필수 조건이라는 것을 두려워합니다. 감사. – Nathan

+0

일반 데이터 구조를 고수하는 것이 좋습니다. 몇 가지 팁으로 내 대답을 업데이트했습니다. –

+0

훌륭한 정보를 제공해 주셔서 감사합니다! 나는 다른 길로가는 것을 끝내었지만 그 수집품, 특히 Wintellects를 조사하기 위해 메모를 만들었습니다. :) – Nathan

0

반환되는 항목의 순서가 정의되지 않았기 때문에 묻는 것은 의미가 없습니다. dictionary에는 주문과 같은 것이 없습니다.

+0

위에서 언급 한 것처럼 미리 예약 된 사전이 있으므로 "의미가 없습니다". – Nathan

+2

표준 Dictionary 클래스는 내부적으로 해시 맵을 기반으로하므로 요소 순서를 유지하지 않으므로 주문할 수 없습니다. – Grizzly

+2

항목이 항상 순서대로 유지된다는 보장은 없습니다. 설명서는 "항목이 반환되는 순서는 정의되지 않았습니다." –

0

내가 생각할 수있는 유일한 방법은 현재 열거 자의 복사본을 만들고 그 중 어떤 것을 가져 오는 것인가 (분명히 꽤 못생긴)이거나, Linq의 .skip() 메서드를 사용하여 앞서 작동하는 열거 형을 만드는 것입니다. 당신 자신을 다시 정의해야하는 어떤 종류의 결합 방법.

다른 점 : 요소의 의미있는 순서를 가지려면 표준 대신에 System.Generics.SortedDictionary을 사용하는 것이 좋습니다. 내가 원래 조각에서 일부 코드를 제거했다 이후

이 방법은 주어진 나는이 똑같이 작동이 것은 보증 할 수

public static IEnumerable<TResult> Combine<TParam1, TParam2, TResult>(this IEnumerable<TParam1> self, IEnumerable<TParam2> other, 
                       Func<TParam1, TParam2, TResult> combiner) 
    { 
     using(var first=self.GetEnumerator()) 
     using (var second = other.GetEnumerator()) 
     { 
      while (first.MoveNext() && second.MoveNext()) 
       yield return combiner(first.Current, second.Current); 
     } 

    } 

적절한 결합기 방법을 두 ienumerables을 결합하는 작업을해야

편집 : 그것에 대해 조금 생각하면, 이것은 당신이 원하는 것을 할 수 있습니다 (unfortenatly C#에서 내 VB가 큰 알이 아니므로) :

skippedEnumerable = myEnumerable;   
myEnumerable.Select(item => {skippedEnumerable = skippedEnumerable.Skip(1); return new KeyValuePair<T, IEnumerable<T>>(item, skippedEnumerable)}); 

이 의지 현재 항목과 현재 위치에서 시작하는 열거 형 쌍을 제공하므로 .ElementAt()를 사용하여 해당 열거 형으로 쉽게 상쇄 할 수 있습니다.이렇게하면 열거 형을 꽤 깊게 중첩 할 수 있으므로 myEnumerable.Skipe(index)을 직접 사용하는 것이 더 좋을 수도 있습니다 (O (n^2) 런타임 때문일 수도 있음).

+0

나는 우아한 linq 접근법을 찾으려고 노력하고 그렇게 할 수 없었다. 접근 방식은 루프가 아닌 초기 쿼리에서 건너 뛸 수를 정의 할 수 있어야한다는 점을 제외하고는 효과가있을 것이라고 생각합니다. 이는 거래 차단기입니다. – Nathan

0

난 당신이 작동해야이 같은 사전 정확히 입력하지만, 뭔가하고 싶은 모르겠어요 :

Dim dict As New Dictionary(Of String, String) 
For i As Integer = 0 To dict.Count - 2 
    If dict.ElementAt(i).Equals(dict.ElementAt(i + 1)) Then Exit For 
Next 

ElementAt을()는 Linq에 함수이다. 그러나 이와 같은 목록을 반복하는 경우 사전이 사용할 것인지 궁금합니다. 일반 목록이 더 좋을 수도 있습니다.

0

대부분의 경우 사전에서 원하는 키 순서로 배열을 만들고 인덱스를 사용하여 반복 할 수 있습니다. , 을하고 사전 [[I] 배열]와 사전 값을 찾아 볼 것입니다

, 당신의 루프가의 비주얼 베이직에 해당 될 것이다 (; 난 < 사항 Array.length을 내가 + + 0 = 난을 INT). 물론 i를 i + 1로 바꿀 수 있습니다 (경계 검사 포함).

1

다음은 미리 들여다 볼 수있는 방법입니다. 질서에 관해서는, 나는 다른 사람들이 이미 언급 한 것을 반복하지 않을 것이다.

Dim peek As Integer = 2 ''// peek ahead amount 
For i As Integer = 0 To tempDictionary.Count - 1 
    Dim key = tempDictionary.Keys(i) 
    Dim value = tempDictionary.Values(i) 
    Console.WriteLine("{0} : {1}", key, value) 

    Dim peekIndex As Integer = i + peek 
    If peekIndex < tempDictionary.Count - 1 Then 
     Dim nextKey = tempDictionary.Keys(peekIndex) 
     Dim nextValue = tempDictionary.Values(peekIndex) 
     Console.WriteLine("Peek: {0} : {1}", nextKey, nextValue) 
    End If 
Next