Как получить отличный экземпляр из списка Лямбдой или LINQ

Вот лучший форматер js money, который я видел:

Number.prototype.formatMoney = function(decPlaces, thouSeparator, decSeparator) {
    var n = this,
        decPlaces = isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces,
        decSeparator = decSeparator == undefined ? "." : decSeparator,
        thouSeparator = thouSeparator == undefined ? "," : thouSeparator,
        sign = n < 0 ? "-" : "",
        i = parseInt(n = Math.abs(+n || 0).toFixed(decPlaces)) + "",
        j = (j = i.length) > 3 ? j % 3 : 0;
    return sign + (j ? i.substr(0, j) + thouSeparator : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thouSeparator) + (decPlaces ? decSeparator + Math.abs(n - i).toFixed(decPlaces).slice(2) : "");
};

Он был переформатирован и заимствован здесь: https://stackoverflow.com/a/149099/751484

Вам нужно будет указать свой собственный обозначение валюты (вы использовали $ выше).

Назовите это так (хотя обратите внимание, что для args по умолчанию задано значение 2, запятая и точка, поэтому вам не нужно указывать аргументы, если вы предпочитаете):

var myMoney=3543.75873;
var formattedMoney = ' + myMoney.formatMoney(2,',','.'); // "$3,543.76"

28
задан phoog 16 April 2012 в 21:11
поделиться

3 ответа

Оба ответа Марка и dahlbyk , кажется, работают очень хорошо. Однако у меня есть гораздо более простое решение. Вместо использования Distinct можно использовать GroupBy . Это выглядит так:

var listDistinct
    = list.GroupBy(
        i => i.value1,
        (key, group) => group.First()
    ).ToArray();

Обратите внимание, что я передал две функции в GroupBy () . Первый - это ключевой селектор. Второй получает только по одному предмету из каждой группы. Из вашего вопроса я предположил, что Первый () был правильным. Вы можете написать другой, если хотите. Вы можете попробовать Last () , чтобы понять, что я имею в виду.

Я провел тест со следующими данными:

var list = new [] {
    new { value1 = "ABC", objT = 0 },
    new { value1 = "ABC", objT = 1 },
    new { value1 = "123", objT = 2 },
    new { value1 = "123", objT = 3 },
    new { value1 = "FOO", objT = 4 },
    new { value1 = "BAR", objT = 5 },
    new { value1 = "BAR", objT = 6 },
    new { value1 = "BAR", objT = 7 },
    new { value1 = "UGH", objT = 8 },
};

Результат был:

//{ value1 = ABC, objT = 0 }
//{ value1 = 123, objT = 2 }
//{ value1 = FOO, objT = 4 }
//{ value1 = BAR, objT = 5 }
//{ value1 = UGH, objT = 8 }

Я не тестировал его на производительность. Я считаю, что это решение, вероятно, немного медленнее, чем решение, использующее Distinct . Несмотря на этот недостаток, есть два больших преимущества: простота и гибкость. Обычно предпочтение отдается простоте, а не оптимизации, но на самом деле это зависит от проблемы, которую вы пытаетесь решить.

59
ответ дан 28 November 2019 в 02:39
поделиться

Проверьте Enumerable.Distinct () , который может принимать компаратор IEqualityComparer:

class MyClassComparer<T> : IEqualityComparer<MyClass<T>>
{
    // Products are equal if their names and product numbers are equal.
    public bool Equals(MyClass<T> x, MyClass<T>y)
    {
        // Check whether the compared objects reference the same data.
        if (Object.ReferenceEquals(x, y)) return true;

        // Check whether any of the compared objects is null.
        if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
            return false;

        // Check whether the products' properties are equal.
        return x.value1 == y.value1;
    }

    // If Equals() returns true for a pair of objects,
    // GetHashCode must return the same value for these objects.

    public int GetHashCode(MyClass<T> x)
    {
        // Check whether the object is null.
        if (Object.ReferenceEquals(x, null)) return 0;

        // Get the hash code for the Name field if it is not null.
        return (x.value1 ?? "").GetHashCode();
    }
}

Ваш фрагмент кода может выглядеть следующим образом:

List<MyClass<T>> list; 
...
List<MyClass<T>> listDistinct = list.Distinct(new MyClassComparer<T>).ToList();
2
ответ дан 28 November 2019 в 02:39
поделиться

Хм ... Я бы, наверное, написал собственный IEqualityComparer , чтобы я мог использовать:

var listDistinct = list.Distinct(comparer).ToList();

и писать компаратор через LINQ ....

Возможно, немного избыточно, но можно использовать повторно, по крайней мере:

Сначала использование:

static class Program {
    static void Main() {
        var data = new[] {
            new { Foo = 1,Bar = "a"}, new { Foo = 2,Bar = "b"}, new {Foo = 1, Bar = "c"}
        };
        foreach (var item in data.DistinctBy(x => x.Foo))
            Console.WriteLine(item.Bar);
        }
    }
}

С служебными методами:

public static class ProjectionComparer
{
    public static IEnumerable<TSource> DistinctBy<TSource,TValue>(
        this IEnumerable<TSource> source,
        Func<TSource, TValue> selector)
    {
        var comparer = ProjectionComparer<TSource>.CompareBy<TValue>(
            selector, EqualityComparer<TValue>.Default);
        return new HashSet<TSource>(source, comparer);
    }
}
public static class ProjectionComparer<TSource>
{
    public static IEqualityComparer<TSource> CompareBy<TValue>(
        Func<TSource, TValue> selector)
    {
        return CompareBy<TValue>(selector, EqualityComparer<TValue>.Default);
    }
    public static IEqualityComparer<TSource> CompareBy<TValue>(
        Func<TSource, TValue> selector,
        IEqualityComparer<TValue> comparer)
    {
        return new ComparerImpl<TValue>(selector, comparer);
    }
    sealed class ComparerImpl<TValue> : IEqualityComparer<TSource>
    {
        private readonly Func<TSource, TValue> selector;
        private readonly IEqualityComparer<TValue> comparer;
        public ComparerImpl(
            Func<TSource, TValue> selector,
            IEqualityComparer<TValue> comparer)
        {
            if (selector == null) throw new ArgumentNullException("selector");
            if (comparer == null) throw new ArgumentNullException("comparer");
            this.selector = selector;
            this.comparer = comparer;
        }

        bool IEqualityComparer<TSource>.Equals(TSource x, TSource y)
        {
            if (x == null && y == null) return true;
            if (x == null || y == null) return false;
            return comparer.Equals(selector(x), selector(y));
        }

        int IEqualityComparer<TSource>.GetHashCode(TSource obj)
        {
            return obj == null ? 0 : comparer.GetHashCode(selector(obj));
        }
    }
}
9
ответ дан 28 November 2019 в 02:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: