목록이 있습니다
List<MyObject> myList
목록에 항목을 추가하고 있으며 해당 개체가 이미 목록에 있는지 확인하고 싶습니다.
그래서 이것을하기 전에 :
myList.Add(nextObject);
nextObject가 이미 목록에 있는지 확인하고 싶습니다.
“MyObject”개체에는 여러 속성이 있지만 비교는 두 속성의 일치를 기반으로합니다.
이 “MyObject”목록에 새 “MyObject”를 추가하기 전에 확인하는 가장 좋은 방법은 무엇입니까?
내가 생각한 유일한 해결책은 목록에서 사전으로 변경 한 다음 키를 속성의 연결된 문자열로 만드는 것입니다 (조금 불분명 해 보입니다).
목록이나 LINQ 또는 다른 것을 사용하는 다른 클리너 솔루션이 있습니까?
답변
특정 상황의 필요에 따라 다릅니다. 예를 들어, 사전 접근 방식은 다음과 같이 가정하면 매우 좋습니다.
- 목록이 비교적 안정적입니다 (사전이 최적화되지 않은 삽입 / 삭제가 많지 않음).
- 목록이 상당히 큽니다 (그렇지 않으면 사전의 오버 헤드가 무의미합니다).
위의 내용이 귀하의 상황에 맞지 않으면 다음 방법을 사용하십시오 Any()
.
Item wonderIfItsPresent = ...
bool containsItem = myList.Any(item => item.UniqueProperty == wonderIfItsPresent.UniqueProperty);
일치하는 항목을 찾거나 끝에 도달 할 때까지 목록을 통해 열거됩니다.
답변
Contains 메서드를 사용하기 만하면됩니다 . 등식 함수를 기반으로 작동합니다.Equals
bool alreadyExist = list.Contains(item);
답변
이 두 가지 속성을 유지 관리 할 수 있다면 다음을 수행 할 수 있습니다.
bool alreadyExists = myList.Any(x=> x.Foo=="ooo" && x.Bar == "bat");
답변
이 경우 목록이 필요합니까? 많은 항목으로 목록을 채우는 경우 성능이 myList.Contains
또는로 인해 저하됩니다 myList.Any
. 런타임은 2 차가됩니다. 더 나은 데이터 구조 사용을 고려할 수 있습니다. 예를 들면
public class MyClass
{
public string Property1 { get; set; }
public string Property2 { get; set; }
}
public class MyClassComparer : EqualityComparer<MyClass>
{
public override bool Equals(MyClass x, MyClass y)
{
if(x == null || y == null)
return x == y;
return x.Property1 == y.Property1 && x.Property2 == y.Property2;
}
public override int GetHashCode(MyClass obj)
{
return obj == null ? 0 : (obj.Property1.GetHashCode() ^ obj.Property2.GetHashCode());
}
}
다음과 같은 방식으로 HashSet을 사용할 수 있습니다.
var set = new HashSet<MyClass>(new MyClassComparer());
foreach(var myClass in ...)
set.Add(myClass);
물론 평등의 정의 MyClass
가 ‘보편적’이라면 IEqualityComparer
구현을 작성할 필요가 없습니다 . 그냥 무시할 수 GetHashCode
및 Equals
클래스 자체입니다.
답변
언급해야 할 또 다른 요점은 평등 함수가 예상대로인지 확인해야한다는 것입니다. 두 인스턴스가 동일한 것으로 간주되기 위해 일치해야하는 개체의 속성을 설정하려면 equals 메서드를 재정의해야합니다.
그런 다음 mylist.contains (item)
답변
다음은 문제 해결 방법에 대한 개념을 설명하는 빠른 콘솔 앱입니다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
public class myobj
{
private string a = string.Empty;
private string b = string.Empty;
public myobj(string a, string b)
{
this.a = a;
this.b = b;
}
public string A
{
get
{
return a;
}
}
public string B
{
get
{
return b;
}
}
}
class Program
{
static void Main(string[] args)
{
List<myobj> list = new List<myobj>();
myobj[] objects = { new myobj("a", "b"), new myobj("c", "d"), new myobj("a", "b") };
for (int i = 0; i < objects.Length; i++)
{
if (!list.Exists((delegate(myobj x) { return (string.Equals(x.A, objects[i].A) && string.Equals(x.B, objects[i].B)) ? true : false; })))
{
list.Add(objects[i]);
}
}
}
}
}
즐겨!
답변
편집 : 나는 처음에 말했다 :
사전 솔루션에 대해 비정상적인 점. 딕셔너리를 생성 할 때 비교기를 설정하기 만하면되기 때문에 나에게 완벽하게 우아해 보인다.
물론 가치이기도 할 때 무언가를 키로 사용하는 것은 우아하지 않습니다.
따라서 HashSet을 사용합니다. 나중에 작업에 인덱싱이 필요한 경우 추가가 완료 될 때 목록을 생성하고 그렇지 않으면 해시 셋을 사용합니다.