C# - 拡張メソッドでIsUniq

拡張メソッドで遊んでみた。
配列内の全ての値がユニークであるかを調べるメソッド「IsUniq」だすぅ。


code-1

//loop 1E6 -> 176ms
public static bool IsUniq<T>(this T[] source)
{
    for (int i = 0; i < source.Length - 1; i++)
    {
        if (Array.IndexOf(source, source[i], i + 1) != -1)
        {
            return false;
        }
    }

    return true;
}


code-2

//非破壊的ソート
public static T[] Sort<T>(this T[] source)
{
    T[] clone = (T[])source.Clone();
    Array.Sort(clone);
    return clone;
}

//loop 1E6 -> 455ms
public static bool IsUniq<T>(this T[] source)
{
    T[] clone = source.Sort();
    for (int i = 0, j = clone.Length - 1; i < j; i++)
    {
        if (clone[i].Equals(clone[i + 1]))
        {
            return false;
        }
    }

    return true;
}
非破壊的ソートメソッドを書き足したのだが、そのせい(?)でパフォーマンスが今一つ。


code-3

//loop 1E6 -> 2050ms
public static bool IsUniq<T>(this T[] source)
{
    for (int i = 0; i < source.Length - 1; i++)
    {
        T tmp = source[i];

        if (source.Skip(i + 1).ToArray().Any((item) => tmp.Equals(item)))
        {
            return false;
        }
    }

    return true;
}
Linqを使ってコードを少々シンプルにした。
やろうとしていることは「code - 1」に近いかな?
パフォーマンス的に論外。


code-4

//loop 1E6 -> 145ms
public static bool IsUniq<T>(this T[] source, Func<T, T, bool> comparer)
{
    int length = source.Length;

    for (int i = 0, j = length - 1; i < j; i++)
    {
        T currentItem = source[i];
        for (int n = i + 1; n < length; n++)
        {
            if (comparer(currentItem, source[n]))
            {
                return false;
            }
        }
    }

    return true;
}
これが一番パフォーマンスが良い結果になった。


Usage

int[] arr = { 12, 34, 56, 78, 90};
bool ret = arr.IsUniq();
//or
//bool ret = arr.IsUniq((x, y) => x == y);



ここからは御ふざけで御座います。

Distinctを使う。
//loop 1E6 -> 787ms
public static bool IsUniq<T>(this T[] source)
{
    return source.Length == ((T[])source.Clone()).Distinct().Count();
}
やはり、配列コピーしたりLinqメソッド使うと重くなるよね。


Whereを使う。
//loop 1E6 -> 1615ms
public static bool IsUniq<T>(this T[] source)
{
    for (int i = 0; i < source.Length - 1; i++)
    {
        T tmp = source[i];

        if (source.Skip(i + 1).Where((item) => tmp.Equals(item)).Count() > 0)
        {
            return false;
        }
    }

    return true;
}
お話になりません。


Allを使う
//loop 1E6 -> 1380ms
public static bool IsUniq<T>(this T[] source)
{
    for (int i = 0; i < source.Length - 1; i++)
    {
        T tmp = source[i];

        if (!source.Skip(i + 1).All((item) => !tmp.Equals(item)))
        {
            return false;
        }
    }

    return true;
}
...飽きた。

0 Comments:

Sony Style(ソニースタイル)
デル株式会社

Recent Posts