programing

목록에 개체가 이미 있는지 확인하는 방법

testmans 2023. 4. 15. 08:29
반응형

목록에 개체가 이미 있는지 확인하는 방법

리스트가 있습니다.

  List<MyObject> myList

목록에 아이템을 추가하고 있는데 해당 오브젝트가 이미 목록에 있는지 확인하고 싶습니다.

이 작업을 수행하기 전에:

 myList.Add(nextObject);

nextObject가 이미 목록에 있는지 확인합니다.

개체 "MyObject"에는 여러 속성이 있지만 두 속성을 기준으로 비교합니다.

이 "MyObject" 목록에 새 "MyObject"를 추가하기 전에 확인하는 가장 좋은 방법은 무엇입니까?

제가 생각한 유일한 해결책은 목록에서 사전으로 변경한 다음 키를 속성의 연결된 문자열로 만드는 것이었습니다(약간 불안정해 보입니다).

목록 또는 LINQ 또는 다른 것을 사용하는 다른 클리너 솔루션이 있습니까?

그것은 특정 상황의 필요에 따라 달라집니다.예를 들어 사전적 접근법은 다음과 같이 가정할 때 매우 적합합니다.

  1. 목록이 비교적 안정적입니다(사전이 최적화되지 않은 삽입/삭제 수가 많지 않음).
  2. 목록이 상당히 큽니다(그렇지 않으면 사전의 오버헤드는 무의미합니다).

위의 내용이 고객의 상황에 맞지 않는 경우는, 다음의 방법을 사용해 주세요.

Item wonderIfItsPresent = ...
bool containsItem = myList.Any(item => item.UniqueProperty == wonderIfItsPresent.UniqueProperty);

일치하는 항목을 찾을 때까지 또는 끝에 도달할 때까지 목록을 열거합니다.

간단히 Contains 메서드를 사용합니다.

bool alreadyExist = list.Contains(item);

이 기능은 등식 함수를 기반으로 작동합니다.Equals구현이 필요한 경우 위의 링크 예를 확인하십시오.Equals기능.

이 두 가지 속성을 사용할 수 있는 경우 다음을 수행할 수 있습니다.

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수업 자체에서요.

또 하나 언급해야 할 점은 평등 기능이 기대한 대로 유지되도록 해야 한다는 것입니다.두 인스턴스가 동일한 것으로 간주되기 위해 일치해야 하는 개체의 속성을 설정하려면 equal 메서드를 재정의해야 합니다.

그럼 mylist.contains(항목)만 하면 됩니다.

다음은 문제를 해결하는 방법에 대한 개념을 설명하는 빠른 콘솔 앱입니다.

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]);
                }
            }
        }
    }
}

맛있게 드세요!

편집: 처음에 말씀드렸습니다.


사전 해결 방법이 뭐가 고상하지 않은가?특히 사전을 만들 때 비교기를 설정하기만 하면 되기 때문에 완벽하게 우아하게 느껴집니다.


물론 가치도 있는데 열쇠로 사용하는 것은 고상하지 않다.

그래서 해시셋을 사용합니다.이후 작업에 인덱싱이 필요한 경우 추가가 완료되면 이 목록에서 목록을 만들고, 그렇지 않은 경우 해시셋만 사용합니다.

심플하지만 효과가 있음

MyList.Remove(nextObject)
MyList.Add(nextObject)

또는

 if (!MyList.Contains(nextObject))
    MyList.Add(nextObject);

컬렉션은 사전으로 사용할 수 있습니다.다만, Microsoft Scripting Runtime 에 대한 참조나 레이트바인딩을 사용할 필요는 없습니다.이 경우 키는 문자열이어야 합니다.이 경우 키(번호)는 정수이지만 문자열로 선언됩니다.커스텀 부울 함수를 생성하여 목록에 키가 있는지 확인할 수 있습니다.ExcelMacroMastery.com에 Paul Kelly라는 좋은 기사가 있습니다.

' Function to check if item in the collection already exists
Function Exists(coll As Collection, key As String) As Boolean

    On Error GoTo EH

    IsObject (coll.Item(key))
    Exists = True

EH:
End Function

end 이렇게 사용할 수 있습니다.

For i = 3 To lastRow
    
        ' Ignore the Normal areas
        If rg.Cells(i, 1).value <> "Normal" Then
        
            number = rg.Cells(i, 1).value
            
            ' Check if the area exist in the collection using a custom function Exists
            If Exists(coll, number) = False Then
            
                Set oRiskArea = New clsHighRiskArea
                oRiskArea.number = number
                coll.add key:=oRiskArea.number, Item:=oRiskArea
                
            Else
                Set oRiskArea = coll(number)
            End If
            
            With oRiskArea
        
                .name = rg.Cells(i, 2).value
        
            End With
            
        End If

    Next i

언급URL : https://stackoverflow.com/questions/3435089/how-to-check-if-object-already-exists-in-a-list

반응형