2013-07-06 1 views
2

두 개의리스트가 교차를 적용하기 전에 값을 공유하는지 알고 싶습니다. 과 같은 것 bool DoIntersect (listA, listB)은 멋질 것입니다!두리스트가 C#에서 값을 공유하는지 확인하십시오.

// Person is a class with Id and Name properties 
List<Person> people1; 
List<Person> people2; 

// Populate people1 and people2... 

// My current solution (pseudocode obviously)... 

if (DoIntersect(people1, people2)) 
{ 
    people1 = people1.Intersect(people2) 
} 
else 
{ 
    /* No shared people */ 
    throw exception; 
} 

// Continue with the process... 
+2

"공유 값"을 정의하십시오. "두리스트 모두 정확히 똑같은 사람들을 포함하고 있습니까?" –

+0

나는 그가 일반적인 가치 (= 인터 섹트)를 가지고 있음을 의미한다고 믿는다. 필요한 방법 인 'Bool DoIntersect (..)'에서 얻을 수있다. –

+0

예, 같은 이드의 사람들. 그러나 사실, 제 코드에는 버그가 있다고 생각합니다. 테스트 해 보도록하겠습니다. – lsibaja

답변

1

그것은 정확하게 당신이 원하는에 따라 달라 중복되지 않는 목록에 대한

// are there any common values between a and b? 
public static bool SharesAnyValueWith<T>(this IEnumerable<T> a, IEnumerable<T> b) 
{ 
    return a.Intersect(b).Any(); 
} 

는, 이것이 반복 한 번 각 ㄴ 것입니다. 겹치는 목록의 경우,이 과정은 처음부터 끝까지 반복되는 요소가 발견 될 때까지 a, b, b를 반복합니다.

// does a contain all of b? (ignores duplicates) 
public static bool ContainsAllFrom<T>(this IEnumerable<T> a, IEnumerable<T> b) 
{ 
    return !b.Except(a).Any(); 
} 

이렇게하면 한 번 반복 한 다음 b를 반복하면서 b의 첫 번째 요소에서 멈 춥니 다.

// does a contain all of b? (considers duplicates) 
public static bool ContainsAllFrom<T>(this IEnumerable<T> a, IEnumerable<T> b) 
{ 
    // get the count of each distinct element in a 
    var counts = a.GroupBy(t => t).ToDictionary(g => g.Key, g => g.Count()); 
    foreach (var t in b) { 
     int count; 
     // if t isn't in a or has too few occurrences return false. Otherwise, reduce 
     // the count by 1 
     if (!counts.TryGetValue(t, out count) || count == 0) { return false; } 
     counts[t] = count - 1; 
    } 

    return true; 
} 

마찬가지로, 이것은 한 번 반복한다 후 B가 아닌 A의 첫번째 요소를 정지 B를 반복한다.

1

내가 믿는 당신이 더 나은 성능을 얻을 수없는 목록을 사용하고 있다는 사실을 변경하지 않고 :

내가 생각 해낸 코드입니다.

두 개의 정렬 된 목록을 먼저 만들려면 (생성시 오버 헤드가 필요함) O (n)의 복잡성을 가지고 반복하여 값을 공유했는지 확인할 수 있습니다.

편집 :

public Boolean DoIntersect(SortedList<int,String> listA,SortedList<int,String> listB ) 
    { 
     if (listA == null || listA.Count == 0 || listB == null || listB.Count == 0) 
     { 
      return false; 
     } 
     var keysA = listA.Keys; 
     var keysB = listB.Keys; 
     int i = 0, j = 0; 
     while (i < listA.Count && j < listB.Count) 
     { 
      if (keysA[i] < keysB[j]) 
      { 
       i++; 
      }else if (keysA[i] > keysB[j]) 
      { 
       j++; 
      } 
      else 
      { 
       return true; 
      } 
     } 

: 원래 영업 이익은 2 사람이 필요합니다 경우, 목록을 분류하지 않지만은 여기 (n)이 O에서 교차로를 확인하기위한 구현

위의 접근법은 IEnumerable 목록에도 사용할 수 있습니다. 즉, GetEnumerator를 사용하여 iterating하고 약간의 변형으로 정렬됩니다.

+0

내 목록이 정렬되지 않았습니다. 내 접근 방식이 괜찮은지 확인해 주셔서 감사합니다. 나는 명성으로 15 점을 얻었을 때 나는 당신의 대답을 유용하다고 표시 할 것이다. 다시 한 번 감사드립니다! – lsibaja

+0

DoIntersect를 여러 번 호출 할 계획이라면 정렬을 유지하는 것이 좋습니다. 반면에 많은 삽입/삭제가있는 경우 정렬하지 않는 것이 좋습니다. 그것은 그 목록에 대한 귀하의 사용에 매우 달려 있습니다. –

관련 문제