LINQ .Any VS .Exists-차이점은 무엇입니까? i.Value)) 과 if(!coll.Exists(i => i.Value)) 업데이트

컬렉션에서 LINQ를 사용하면 다음 코드 줄의 차이점은 무엇입니까?

if(!coll.Any(i => i.Value))

if(!coll.Exists(i => i.Value))

업데이트 1

분해 .Exists할 때 코드가없는 것처럼 보입니다.

업데이트 2

아무도이 코드가없는 이유를 알고 있습니까?



답변

설명서 참조

List.Exist (오브젝트 메소드-MSDN)

List (T)에 지정된 조건 자에 의해 정의 된 조건과 일치하는 요소가 포함되어 있는지 확인합니다.

이것은 .NET 2.0 이후 LINQ 이전에 존재합니다. Predicate delegate 와 함께 사용 되지만 람다 식은 이전 버전과 호환됩니다. 또한 List만이 이것을 가지고 있습니다 (IList조차도 아닙니다)

IEnumerable.Any (확장 방법-MSDN)

시퀀스의 요소가 조건을 만족하는지 여부를 결정합니다.

이것은 .NET 3.5의 새로운 기능이며 Func (TSource, bool)를 인수로 사용하므로 람다 식 및 LINQ와 함께 사용됩니다.

행동에서, 이들은 동일합니다.


답변

차이점은 Any는 IEnumerable<T>System.Linq.Enumerable에 정의 된 모든 확장 방법이라는 것입니다 . 모든 IEnumerable<T>인스턴스에서 사용할 수 있습니다 .

존재하는 확장 방법이 아닌 것 같습니다. 내 생각에 콜은 유형 List<T>입니다. 그렇다면 Exists는 Any와 매우 유사한 기능을하는 인스턴스 방법입니다.

요컨대 , 방법은 본질적으로 동일합니다. 하나는 다른 것보다 더 일반적입니다.

  • 어떤은 또한 매개 변수를 사용하지 않는 단순히 열거에있는 모든 항목을 찾습니다 과부하가 있습니다.
  • 기존 과부하가 없습니다.

답변

TLDR; 성능면 Any에서는 속도가 느린 것 같습니다 (거의 동시에 두 값을 모두 평가하도록 올바르게 설정하면)

        var list1 = Generate(1000000);
        var forceListEval = list1.SingleOrDefault(o => o == "0123456789012");
        if (forceListEval != "sdsdf")
        {
            var s = string.Empty;
            var start2 = DateTime.Now;
            if (!list1.Exists(o => o == "0123456789012"))
            {
                var end2 = DateTime.Now;
                s += " Exists: " + end2.Subtract(start2);
            }

            var start1 = DateTime.Now;
            if (!list1.Any(o => o == "0123456789012"))
            {
                var end1 = DateTime.Now;
                s +=" Any: " +end1.Subtract(start1);
            }

            if (!s.Contains("sdfsd"))
            {

            }

테스트 목록 생성기 :

private List<string> Generate(int count)
    {
        var list = new List<string>();
        for (int i = 0; i < count; i++)
        {
            list.Add( new string(
            Enumerable.Repeat("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 13)
                .Select(s =>
                {
                    var cryptoResult = new byte[4];
                    new RNGCryptoServiceProvider().GetBytes(cryptoResult);
                    return s[new Random(BitConverter.ToInt32(cryptoResult, 0)).Next(s.Length)];
                })
                .ToArray()));
        }

        return list;
    }

10M 기록

“모두 : 00 : 00 : 00.3770377 기존 : 00 : 00 : 00.2490249”

5M 기록

“모두 : 00 : 00 : 00.0940094 기존 : 00 : 00 : 00.1420142”

1M 기록

“모두 : 00 : 00 : 00.0180018 기존 : 00 : 00 : 00.0090009”

500k로 (나는 또한 어느 것이 먼저 실행되는지와 관련된 추가 작업이 없는지 확인하기 위해 평가되는 순서를 뒤집 었습니다.)

“기존 : 00 : 00 : 00.0050005 모두 : 00 : 00 : 00.0100010”

100k 레코드

“기존 : 00 : 00 : 00.0010001 모두 : 00 : 00 : 00.0020002”

Any2의 크기만큼 느려질 것 같습니다 .

편집 : 5M 및 10M 레코드의 경우 목록을 생성하는 방식을 변경하고 Exists갑자기 Any테스트하는 방식에 문제가 있음을 의미하는 것보다 느려졌습니다 .

새로운 테스트 메커니즘 :

private static IEnumerable<string> Generate(int count)
    {
        var cripto = new RNGCryptoServiceProvider();
        Func<string> getString = () => new string(
            Enumerable.Repeat("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 13)
                .Select(s =>
                {
                    var cryptoResult = new byte[4];
                    cripto.GetBytes(cryptoResult);
                    return s[new Random(BitConverter.ToInt32(cryptoResult, 0)).Next(s.Length)];
                })
                .ToArray());

        var list = new ConcurrentBag<string>();
        var x = Parallel.For(0, count, o => list.Add(getString()));
        return list;
    }

    private static void Test()
    {
        var list = Generate(10000000);
        var list1 = list.ToList();
        var forceListEval = list1.SingleOrDefault(o => o == "0123456789012");
        if (forceListEval != "sdsdf")
        {
            var s = string.Empty;

            var start1 = DateTime.Now;
            if (!list1.Any(o => o == "0123456789012"))
            {
                var end1 = DateTime.Now;
                s += " Any: " + end1.Subtract(start1);
            }

            var start2 = DateTime.Now;
            if (!list1.Exists(o => o == "0123456789012"))
            {
                var end2 = DateTime.Now;
                s += " Exists: " + end2.Subtract(start2);
            }

            if (!s.Contains("sdfsd"))
            {

            }
        }

Edit2 : 테스트 데이터 생성에 따른 영향을 제거하기 위해 파일에 모두 쓰고 이제 거기에서 읽습니다.

 private static void Test()
    {
        var list1 = File.ReadAllLines("test.txt").Take(500000).ToList();
        var forceListEval = list1.SingleOrDefault(o => o == "0123456789012");
        if (forceListEval != "sdsdf")
        {
            var s = string.Empty;
            var start1 = DateTime.Now;
            if (!list1.Any(o => o == "0123456789012"))
            {
                var end1 = DateTime.Now;
                s += " Any: " + end1.Subtract(start1);
            }

            var start2 = DateTime.Now;
            if (!list1.Exists(o => o == "0123456789012"))
            {
                var end2 = DateTime.Now;
                s += " Exists: " + end2.Subtract(start2);
            }

            if (!s.Contains("sdfsd"))
            {
            }
        }
    }

10M

“모두 : 00 : 00 : 00.1640164 기존 : 00 : 00 : 00.0750075”

5M

“모두 : 00 : 00 : 00.0810081 기존 : 00 : 00 : 00.0360036”

1M

“모두 : 00 : 00 : 00.0190019 기존 : 00 : 00 : 00.0070007”

500k

“모두 : 00 : 00 : 00.0120012 기존 : 00 : 00 : 00.0040004”

여기에 이미지 설명을 입력하십시오


답변

벤치마킹 에 대한 Matas의 답변 을 계속합니다 .

TL / DR : Exists ()와 Any ()는 똑같이 빠릅니다.

우선 : 스톱워치를 사용한 벤치마킹은 정확하지 않지만 ( 다른 주제 이지만 주제가 많은 series0ne의 답변 참조 ) DateTime보다 훨씬 정확합니다.

실제로 정확한 측정 값을 얻는 방법은 성능 프로파일 링을 사용하는 것입니다. 그러나 두 방법의 성능을 서로 측정하는 방법을 이해하는 한 가지 방법은 두 방법을 모두 로드 한 다음 가장 빠른 실행 시간을 비교하는 것입니다. 그 방법은, 정말 JITing 및 기타 노이즈가 우리에게 나쁜 판독을 제공 (그리고 그 중요하지 않습니다 않습니다 모두 처형 “하기 때문에,) 똑같이 misguiding 의미에서”.

static void Main(string[] args)
    {
        Console.WriteLine("Generating list...");
        List<string> list = GenerateTestList(1000000);
        var s = string.Empty;

        Stopwatch sw;
        Stopwatch sw2;
        List<long> existsTimes = new List<long>();
        List<long> anyTimes = new List<long>();

        Console.WriteLine("Executing...");
        for (int j = 0; j < 1000; j++)
        {
            sw = Stopwatch.StartNew();
            if (!list.Exists(o => o == "0123456789012"))
            {
                sw.Stop();
                existsTimes.Add(sw.ElapsedTicks);
            }
        }

        for (int j = 0; j < 1000; j++)
        {
            sw2 = Stopwatch.StartNew();
            if (!list.Exists(o => o == "0123456789012"))
            {
                sw2.Stop();
                anyTimes.Add(sw2.ElapsedTicks);
            }
        }

        long existsFastest = existsTimes.Min();
        long anyFastest = anyTimes.Min();

        Console.WriteLine(string.Format("Fastest Exists() execution: {0} ticks\nFastest Any() execution: {1} ticks", existsFastest.ToString(), anyFastest.ToString()));
        Console.WriteLine("Benchmark finished. Press any key.");
        Console.ReadKey();
    }

    public static List<string> GenerateTestList(int count)
    {
        var list = new List<string>();
        for (int i = 0; i < count; i++)
        {
            Random r = new Random();
            int it = r.Next(0, 100);
            list.Add(new string('s', it));
        }
        return list;
    }

위의 코드를 (다시 1000을 4 번 실행 한 후 Exists()Any()1 개 000 000 요소가있는 목록을),이 방법은 거의 동일하게 빠른 것을 볼 어렵지 않다.

Fastest Exists() execution: 57881 ticks
Fastest Any() execution: 58272 ticks

Fastest Exists() execution: 58133 ticks
Fastest Any() execution: 58063 ticks

Fastest Exists() execution: 58482 ticks
Fastest Any() execution: 58982 ticks

Fastest Exists() execution: 57121 ticks
Fastest Any() execution: 57317 ticks

있습니다 약간의 차이는 있지만, 배경 잡음에 의해 설명 할 수없는 너무 작은 차이입니다. 내 생각 엔 한 10 000 100 000을한다면 있다는 것 Exists()Any()대신에, 그 약간의 차이가 다소 사라질 것이다.


답변

또한 Value가 bool 유형 인 경우에만 작동합니다. 일반적으로 이것은 술어와 함께 사용됩니다. 주어진 조건을 만족하는 요소가 있는지를 찾기 위해 모든 술어가 일반적으로 사용됩니다. 여기서 당신은 요소 i에서 bool 속성으로의 맵을 수행하고 있습니다. Value 속성이 true 인 “i”를 검색합니다. 완료되면 메소드는 true를 리턴합니다.


답변

위에서 언급 한 바와 같이 측정을 수정하면 다음과 같은 결과가 나타납니다.

Executing search Exists() 1000 times ...
Average Exists(): 35566,023
Fastest Exists() execution: 32226

Executing search Any() 1000 times ...
Average Any(): 58852,435
Fastest Any() execution: 52269 ticks

Benchmark finished. Press any key.


답변