කිසියම් දේපලක් මත ලින්ක් හි වෙනස ()


1134

මම ඒ ගැන ඉගෙන ගැනීමට LINQ සමඟ සෙල්ලම් කරමි, නමුත් මට Distinctසරල ලැයිස්තුවක් නොමැති විට භාවිතා කරන්නේ කෙසේදැයි මට සිතාගත නොහැක (පූර්ණ සංඛ්‍යා ලැයිස්තුවක් කිරීම පහසුය, මෙය ප්‍රශ්නය නොවේ). වස්තුවක ගුණාංග එකක් හෝ වැඩි ගණනක වස්තුවක ලැයිස්තුවක් මත වෙනස භාවිතා කිරීමට අවශ්‍ය නම් මා කුමක් කළ යුතුද?

උදාහරණය: වස්තුවක් නම් Person, දේපල සමඟ Id. සියලු පුද්ගලයින් ලබාගෙන වස්තුවේ Distinctදේපල සමඟ ඔවුන් භාවිතා කරන්නේ Idකෙසේද?

Person1: Id=1, Name="Test1"
Person2: Id=1, Name="Test1"
Person3: Id=2, Name="Test2"

මට සාධාරණව Person1සහ Person3කෙසේද? එය කළ හැකිද?

LINQ සමඟ එය කළ නොහැකි නම්, Person.NET 3.5 හි ඇති සමහර ගුණාංග මත පදනම්ව ලැයිස්තුවක් තබා ගැනීමට හොඳම ක්‍රමය කුමක්ද?

Answers:


1281

සංස්කරණය කරන්න : මෙය දැන් MoreLINQ හි කොටසකි .

ඔබට අවශ්‍ය වන්නේ “වෙනස් ආකාරයකින්” .ලදායී ලෙස ය. එය ලිවීමට තරමක් පහසු වුවත්, එය ලින්ක්හි කොටසක් බව මම විශ්වාස නොකරමි:

public static IEnumerable<TSource> DistinctBy<TSource, TKey>
    (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
    HashSet<TKey> seenKeys = new HashSet<TKey>();
    foreach (TSource element in source)
    {
        if (seenKeys.Add(keySelector(element)))
        {
            yield return element;
        }
    }
}

එබැවින් Idදේපල පමණක් භාවිතා කරමින් පැහැදිලි අගයන් සොයා ගැනීමට ඔබට භාවිතා කළ හැකිය:

var query = people.DistinctBy(p => p.Id);

බහු ගුණාංග භාවිතා කිරීම සඳහා, ඔබට සමානාත්මතාවය නිසි පරිදි ක්‍රියාත්මක කරන නිර්නාමික වර්ග භාවිතා කළ හැකිය:

var query = people.DistinctBy(p => new { p.Id, p.Name });

පරීක්ෂා නොකළ නමුත් එය ක්‍රියාත්මක විය යුතුය (එය දැන් අවම වශයෙන් සම්පාදනය කරයි).

එය යතුරු සඳහා පෙරනිමි සංසන්දකය උපකල්පනය කරයි - ඔබට සමානාත්මතා සංසන්දකය තුළ සමත් වීමට අවශ්‍ය නම්, එය HashSetඉදිකිරීම්කරු වෙත භාර දෙන්න.



2
@ ashes999: ඔබ අදහස් කරන්නේ කුමක්දැයි මට විශ්වාස නැත. කේතය පිළිතුරෙහි සහ පුස්තකාලයේ පවතී - යැපීමක් ලබා ගැනීමට ඔබ සතුටු වන්නේද යන්න මත පදනම්ව.
ජෝන් ස්කීට්

11
@ ashes999: ඔබ මෙය කරන්නේ එකම ස්ථානයක නම්, කවදා හෝ, නිසැකවම, භාවිතා GroupByකිරීම සරල ය. ඔබට එය එක් ස්ථානයකට වඩා අවශ්‍ය නම්, අභිප්‍රාය වටහා ගැනීම වඩා පිරිසිදු (IMO) වේ.
ජෝන් ස්කීට්

6
Att මැතිව්විත්: මෙහි කිසිදු සඳහනක් නොමැති හෙයින් IQueryable<T>, එය අදාළ වන්නේ කෙසේදැයි මම නොදනිමි. මෙය EF යනාදිය සඳහා සුදුසු නොවන බව මම එකඟ වෙමි, නමුත් LINQ to Objects තුළ එය වඩා සුදුසු යැයි මම සිතමිGroupBy . ප්රශ්නයේ සන්දර්භය සෑම විටම වැදගත් වේ.
ජෝන් ස්කීට්

8
මෙම ව්‍යාපෘතිය ගිතුබ් වෙත ගෙන යන ලදී, මෙන්න DistinctBy කේතය: github.com/morelinq/MoreLINQ/blob/master/MoreLinq/DistinctBy.cs
Phate01

1915

දේපල එකක් හෝ කිහිපයක් මත පදනම්ව පැහැදිලි ලැයිස්තුවක් ලබා ගැනීමට මට අවශ්‍ය නම් කුමක් කළ යුතුද?

සරල! ඔබට ඒවා කණ්ඩායම් කර ජයග්‍රාහකයෙකු කණ්ඩායමෙන් තෝරා ගැනීමට අවශ්‍යය.

List<Person> distinctPeople = allPeople
  .GroupBy(p => p.PersonId)
  .Select(g => g.First())
  .ToList();

ඔබට බහු ගුණාංග මත කණ්ඩායම් අර්ථ දැක්වීමට අවශ්‍ය නම්, මෙන්න:

List<Person> distinctPeople = allPeople
  .GroupBy(p => new {p.PersonId, p.FavoriteColor} )
  .Select(g => g.First())
  .ToList();

2
@ErenErsonmez විශ්වාසයි. මගේ පළ කරන ලද කේතය සමඟ, කල් දැමූ ක්‍රියාත්මක කිරීම අවශ්‍ය නම්, ටොලිස්ට් ඇමතුම අත්හරින්න.
ඇමී බී

6
හරිම ලස්සන පිළිතුරක්! මට දර්ශනය වෙනස් කිරීමට නොහැකි වූ වර්ග අඩි දර්ශනයකින් ධාවනය වන ලින්ක්-ටු-එන්ටිටීස් සඳහා රියල්ලි මට උදව් කළේය. මට පළමු () වෙනුවට FirstOrDefault () භාවිතා කිරීමට අවශ්‍ය විය - සියල්ල හොඳයි.
ඇලෙක්ස් කීස්මිත්

10
මම එය උත්සාහ කළ අතර එය තේරීම (g => g.FirstOrDefault ()) ලෙස වෙනස් විය යුතුය

27
Oc චොකැපික්ස් ස්නෝප්. ප්‍රභවයට අයිතම එකකට වඩා ඇති විට දෙකම Single()සහ SingleOrDefault()එක් එක් විසි කිරීම. මෙම මෙහෙයුමේදී, සෑම කණ්ඩායමකටම එක අයිතමයක් තිබිය හැකි බව අපි අපේක්ෂා කරමු. ඒ සඳහා, First()වඩාත් කැමති FirstOrDefault()වන්නේ සෑම කණ්ඩායමකටම අවම වශයෙන් එක් සාමාජිකයෙකු සිටිය යුතු බැවිනි .... ඔබ EntityFramework භාවිතා නොකරන්නේ නම්, සෑම කණ්ඩායමකටම අවම වශයෙන් එක් සාමාජිකයෙකු හෝ ඉල්ලීම් ඇති බව හඳුනාගත නොහැක FirstOrDefault().
ඇමී බී

3
FirstOrDefault() Github.com/dotnet/efcore/issues/12088 භාවිතා කරමින් පවා ඊඑෆ් කෝර් හි දැනට සහාය නොදක්වන බව පෙනේ, මම 3.1 හි සිටිමි, මට "පරිවර්තනය කිරීමට නොහැකි" දෝෂ ඇතිවේ .
කොලින් එම්. බැරට්

84

භාවිත:

List<Person> pList = new List<Person>();
/* Fill list */

var result = pList.Where(p => p.Name != null).GroupBy(p => p.Id).Select(grp => grp.FirstOrDefault());

මෙම whereඔබ ඇතුළත් කිරීම් (වඩාත් සංකීර්ණ විය හැකි) සහ පෙරීමට උපකාරී groupbyහා selectපැවති විශේෂ කාර්යයක් ඉටු.


2
පරිපූර්ණ, සහ ලින්ක් දිගු නොකර හෝ වෙනත් යැපීමක් භාවිතා නොකර ක්‍රියා කරයි.
ඩේවිඩ්චෙරර්

මෙහි විශිෂ්ට පිළිතුරක්. ස්තූතියි
riketscience

79

ඔබට ලින්ක් වැනි පෙනුමක් ලබා ගැනීමට අවශ්‍ය නම් විමසුම් සින්ටැක්ස් භාවිතා කළ හැකිය:

var uniquePeople = from p in people
                   group p by new {p.ID} //or group by new {p.ID, p.Name, p.Whatever}
                   into mygroup
                   select mygroup.FirstOrDefault();

4
හ්ම් මගේ සිතුවිලි විමසුම් වාක්‍ය ඛණ්ඩය වන අතර චතුර කථික API වාක්‍ය ඛණ්ඩය එකිනෙකට සමාන ලින්ක් මෙන්ම මිනිසුන් භාවිතා කරන ඒවාට වඩා මනාපය. මම චතුර කථික ඒපීඅයි වලට වැඩි කැමැත්තක් දක්වන්නෙමි, එබැවින් මම එය වඩා ලින්ක්-ලයික් ලෙස සලකමි, නමුත් එය ආත්මීය යැයි මම සිතමි
මැක්ස් කැරොල්

ලින්ක්-ලයික් මනාපයට කිසිදු සම්බන්ධයක් නැත, "ලින්ක්-වැනි" වීම සී # තුළට වෙනත් විමසුම් භාෂාවක් කාවැද්දීම හා සම්බන්ධ විය යුතුය, මම වඩාත් කැමති චතුර කථික අතුරුමුහුණත, ජාවා ප්‍රවාහයන්ගෙන් එන නමුත් එය ලින්ක්-ලයික් නොවේ.
රයන් ද ලීච්

විශිෂ්ටයි !! ඔයා මගේ වීරයා!
ෆාර්සින් කන්සි

65

මම හිතන්නේ එය ප්‍රමාණවත් ය:

list.Select(s => s.MyField).Distinct();

45
එම ක්ෂේත්‍රය පමණක් නොව, ඔහුගේ සම්පූර්ණ වස්තුව ආපසු අවශ්‍ය නම් කුමක් කළ යුතුද?
ෆෙස්ටිම් කහානි

1
එකම දේපල වටිනාකමක් ඇති වස්තු කිහිපයක නිශ්චිත වස්තුව කුමක්ද?
donRumatta

41

ඔබේ ක්ෂේත්‍ර අනුව පළමු කණ්ඩායම විසඳන්න, පසුව පළමු ඇණවුම් අයිතමය තෝරන්න.

    List<Person> distinctPeople = allPeople
   .GroupBy(p => p.PersonId)
   .Select(g => g.FirstOrDefault())
   .ToList();

27

ඔබට මෙය සම්මතයෙන් කළ Linq.ToLookup()හැකිය. මෙය එක් එක් අද්විතීය යතුර සඳහා අගයන් එකතුවක් නිර්මාණය කරනු ඇත. එකතුවේ පළමු අයිතමය තෝරන්න

Persons.ToLookup(p => p.Id).Select(coll => coll.First());

17

පහත කේතය ජෝන් ස්කීට්ගේ පිළිතුරට ක්‍රියාකාරීව සමාන වේ .

.NET 4.5 හි පරීක්ෂා කර ඇති අතර, LINQ හි ​​ඕනෑම පෙර සංස්කරණයක් මත ක්‍රියා කළ යුතුය.

public static IEnumerable<TSource> DistinctBy<TSource, TKey>(
  this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
  HashSet<TKey> seenKeys = new HashSet<TKey>();
  return source.Where(element => seenKeys.Add(keySelector(element)));
}

අහම්බෙන්, ගූගල් කේතයේ ජෝන් ස්කීට් හි DistinctBy.cs හි නවතම අනුවාදය බලන්න .


3
මෙය මට "අනුක්‍රමයකට සාරධර්ම දෝෂයක් නැත", නමුත් ස්කීට්ගේ පිළිතුර නිවැරදි ප්‍රති .ලය ලබා දුන්නේය.
සිසිල් වන්නේ කුමක් ද?

10

පහත දැක්වෙන පරිදි ඔබට කළ හැකි වන පරිදි සුවිශේෂී ශ්‍රිතය දීර් extend කරන්නේ කෙසේද යන්න පැහැදිලි කරන ලිපියක් මා ලියා ඇත:

var people = new List<Person>();

people.Add(new Person(1, "a", "b"));
people.Add(new Person(2, "c", "d"));
people.Add(new Person(1, "a", "b"));

foreach (var person in people.Distinct(p => p.ID))
    // Do stuff with unique list here.

මෙන්න ලිපිය: LINQ දීර් tend කිරීම - පැහැදිලි ශ්‍රිතයේ දේපලක් නියම කිරීම


3
ඔබේ ලිපියේ දෝෂයක් තිබේ, වෙනසකට පසු <T> තිබිය යුතුය: පොදු ස්ථිතික IEnumerable <T> වෙනස (මෙය ... එසේම එය එක් දේපලකට වඩා වැඩියෙන් (මනාව) ක්‍රියාත්මක වන බවක් නොපෙනේ, එනම් පළමු සංයෝජනය සහ අවසාන නම්.
පේළිය 1

2
+1, සුළු දෝෂයක් පහත වැටීමට ප්‍රමාණවත් හේතුවක් නොවේ, එතරම් මෝඩ, බොහෝ විට යතුරු ලියනය ලෙස හැඳින්වේ. තවද, දේපල ගණනාවකට වැඩ කරන සාමාන්‍ය ශ්‍රිතයක් මා තවම දැක නැත! මෙම ත්‍රෙඩ් එකේ අනෙක් සෑම පිළිතුරක්ම ඩවුන්වෝටර් පහත් කොට ඇති බව මම විශ්වාස කරමි. ඒයි, මේ දෙවන වර්ගයේ වස්තුව කුමක්ද? මම විරුද්ධයි!
nawfal

5
ඔබේ සබැඳිය කැඩී ඇත
ටොම් ලින්ට්

7

පුද්ගලිකව මම පහත පන්තිය භාවිතා කරමි:

public class LambdaEqualityComparer<TSource, TDest> : 
    IEqualityComparer<TSource>
{
    private Func<TSource, TDest> _selector;

    public LambdaEqualityComparer(Func<TSource, TDest> selector)
    {
        _selector = selector;
    }

    public bool Equals(TSource obj, TSource other)
    {
        return _selector(obj).Equals(_selector(other));
    }

    public int GetHashCode(TSource obj)
    {
        return _selector(obj).GetHashCode();
    }
}

පසුව, දිගු කිරීමේ ක්‍රමයක්:

public static IEnumerable<TSource> Distinct<TSource, TCompare>(
    this IEnumerable<TSource> source, Func<TSource, TCompare> selector)
{
    return source.Distinct(new LambdaEqualityComparer<TSource, TCompare>(selector));
}

අවසාන වශයෙන්, අපේක්ෂිත භාවිතය:

var dates = new List<DateTime>() { /* ... */ }
var distinctYears = dates.Distinct(date => date.Year);

මෙම ප්‍රවේශය භාවිතා කිරීමෙන් මා සොයාගත් වාසිය LambdaEqualityComparerනම්, පිළිගන්නා වෙනත් ක්‍රම සඳහා පන්තිය නැවත භාවිතා කිරීමයි IEqualityComparer. (ඔහ්, මම yieldමුල් ලින්ක් ක්‍රියාත්මක කිරීම සඳහා දේවල් තබමි ...)


6

වස්තු දේපලකින් පැහැදිලි වාර්තා ලබා ගැනීම සඳහා ඔබට DistinctBy () භාවිතා කළ හැකිය. එය භාවිතා කිරීමට පෙර පහත ප්‍රකාශය එක් කරන්න:

Microsoft.Ajax.Utilities භාවිතා කිරීම;

ඉන්පසු එය පහත පරිදි භාවිතා කරන්න:

var listToReturn = responseList.DistinctBy(x => x.Index).ToList();

'දර්ශකය' යනු දත්ත එකිනෙකට වෙනස් වීමට මට අවශ්‍ය දේපලයි.


5

ඔබට බහු ගුණාංග පිළිබඳ විශේෂිත ක්‍රමයක් අවශ්‍ය නම්, ඔබට මගේ බලවත් දිගුවන් පරීක්ෂා කළ හැකිය පුස්තකාලය . දැනට එය ඉතා තරුණ අවධියක පවතී, නමුත් දැනටමත් ඔබට ඕනෑම දේපල ගණනක් හැර වෙන වෙනම, යුනියන්, ඉන්ටර්සෙක්ට් වැනි ක්‍රම භාවිතා කළ හැකිය;

ඔබ එය භාවිතා කරන ආකාරය මෙයයි:

using PowerfulExtensions.Linq;
...
var distinct = myArray.Distinct(x => x.A, x => x.B);

5

අපගේ ව්‍යාපෘතියේ එවැනි කාර්යයකට අප මුහුණ දුන් විට, සංසන්දකයන් රචනා කිරීම සඳහා අපි කුඩා API එකක් අර්ථ දැක්වුවෙමු.

ඉතින්, භාවිත නඩුව මේ වගේ විය:

var wordComparer = KeyEqualityComparer.Null<Word>().
    ThenBy(item => item.Text).
    ThenBy(item => item.LangID);
...
source.Select(...).Distinct(wordComparer);

ඒපීඅයි එක මේ වගේ ය:

using System;
using System.Collections;
using System.Collections.Generic;

public static class KeyEqualityComparer
{
    public static IEqualityComparer<T> Null<T>()
    {
        return null;
    }

    public static IEqualityComparer<T> EqualityComparerBy<T, K>(
        this IEnumerable<T> source,
        Func<T, K> keyFunc)
    {
        return new KeyEqualityComparer<T, K>(keyFunc);
    }

    public static KeyEqualityComparer<T, K> ThenBy<T, K>(
        this IEqualityComparer<T> equalityComparer,
        Func<T, K> keyFunc)
    {
        return new KeyEqualityComparer<T, K>(keyFunc, equalityComparer);
    }
}

public struct KeyEqualityComparer<T, K>: IEqualityComparer<T>
{
    public KeyEqualityComparer(
        Func<T, K> keyFunc,
        IEqualityComparer<T> equalityComparer = null)
    {
        KeyFunc = keyFunc;
        EqualityComparer = equalityComparer;
    }

    public bool Equals(T x, T y)
    {
        return ((EqualityComparer == null) || EqualityComparer.Equals(x, y)) &&
                EqualityComparer<K>.Default.Equals(KeyFunc(x), KeyFunc(y));
    }

    public int GetHashCode(T obj)
    {
        var hash = EqualityComparer<K>.Default.GetHashCode(KeyFunc(obj));

        if (EqualityComparer != null)
        {
            var hash2 = EqualityComparer.GetHashCode(obj);

            hash ^= (hash2 << 5) + hash2;
        }

        return hash;
    }

    public readonly Func<T, K> KeyFunc;
    public readonly IEqualityComparer<T> EqualityComparer;
}

වැඩි විස්තර අපගේ වෙබ් අඩවියේ ඇත: LINQ හි ​​IEqualityComparer .


4

ඔබට එය කළ හැකිය (අකුණු වේගයෙන් නොවුනත්):

people.Where(p => !people.Any(q => (p != q && p.Id == q.Id)));

එනම්, "එකම හැඳුනුම්පතක් ඇති ලැයිස්තුවේ වෙනත් වෙනස් පුද්ගලයෙක් නොමැති සියලු පුද්ගලයින් තෝරන්න."

ඔබේ උදාහරණයේ දී, එය පුද්ගලයකු 3 ක් පමණක් තෝරා ගනු ඇතැයි සිතන්න. පෙර දෙකෙන් ඔබට අවශ්‍ය දේ කීමට මට විශ්වාස නැත.


4

DistinctByක්‍රියාකාරීත්වය ලබා ගැනීම සඳහා ඔබේ ව්‍යාපෘතියට මෝර්ලින්ක් පුස්තකාලය එක් කිරීමට ඔබට අවශ්‍ය නැතිනම්, ලින්ක්ගේ Distinctක්‍රමවේදය අධික ලෙස භාවිතා කිරීමෙන් ඔබට එකම අවසාන ප්‍රති result ලය ලබා ගත හැකිය .IEqualityComparer .

සාමාන්‍ය පන්තියේ අවස්ථා දෙකක අභිරුචි සංසන්දනය කිරීම සඳහා ලැම්බඩා සින්ටැක්ස් භාවිතා කරන සාමාන්‍ය අභිරුචි සමානාත්මතා සංසන්දනාත්මක පන්තියක් නිර්මාණය කිරීමෙන් ඔබ ආරම්භ කරයි:

public class CustomEqualityComparer<T> : IEqualityComparer<T>
{
    Func<T, T, bool> _comparison;
    Func<T, int> _hashCodeFactory;

    public CustomEqualityComparer(Func<T, T, bool> comparison, Func<T, int> hashCodeFactory)
    {
        _comparison = comparison;
        _hashCodeFactory = hashCodeFactory;
    }

    public bool Equals(T x, T y)
    {
        return _comparison(x, y);
    }

    public int GetHashCode(T obj)
    {
        return _hashCodeFactory(obj);
    }
}

ඔබේ ප්‍රධාන කේතයේ ඔබ එය එසේ භාවිතා කරයි:

Func<Person, Person, bool> areEqual = (p1, p2) => int.Equals(p1.Id, p2.Id);

Func<Person, int> getHashCode = (p) => p.Id.GetHashCode();

var query = people.Distinct(new CustomEqualityComparer<Person>(areEqual, getHashCode));

වොයිලා! :)

ඉහත සඳහන් කරුණු පහත දැක්වේ:

  • දේපල Person.Idවර්ගයට අයත් වේint
  • මෙම peopleඑකතුව ඕනෑම ශූන්ය අංග අඩංගු නොවේ

එකතුවට ශුන්‍ය අඩංගු විය හැකි නම්, ශුන්‍යය පරීක්ෂා කිරීම සඳහා ලැම්බඩා නැවත ලියන්න, උදා:

Func<Person, Person, bool> areEqual = (p1, p2) => 
{
    return (p1 != null && p2 != null) ? int.Equals(p1.Id, p2.Id) : false;
};

සංස්කරණය කරන්න

මෙම ප්‍රවේශය ව්ලැඩිමීර් නෙස්ටරොව්ස්කිගේ පිළිතුරට සමාන නමුත් සරල ය.

එය ජොයෙල්ගේ පිළිතුරේ ඇති පිළිතුරට සමාන වන නමුත් බහු ගුණාංග සම්බන්ධ සංකීර්ණ සංසන්දනාත්මක තර්කනයකට ඉඩ දෙයි.

කෙසේ වෙතත්, ඔබගේ වස්තූන් පමණක් මෙතෙක් විසින් වෙනස් කළ හැකි නම් Idඑවිට තවත් පරිශීලකයෙකු නිවැරදි පිළිතුර ලබා දුන් ඔබ කළ යුතු සියල්ල පෙරනිමි නිර්මාණයන් යටපත් කිරීම බව GetHashCode()හා Equals()ඔබේ Personපන්තිය හා ඉන්පසු එහි සිදු-of-the-කොටුව භාවිතා Distinct()පෙරහන Linq ක්රමය ඕනෑම අනුපිටපත්.


මට අවශ්‍ය වන්නේ ආ ict ාදායකයේ අද්විතීය අයිතම පමණක් ලබා ගැනීමටයි, ඔබට උදව් කළ හැකිද, මම මෙම කේතය භාවිතා කරන්නේ TempDT IsNot කිසිවක් නොවේ නම් m_ConcurrentScriptDictionary = TempDT.AsEnumerable.ToDictionary (Function (x) x.SafeField (fldClusterId, NULL_ID_VALUE) y.SafeField (fldParamValue11, NULL_ID_VALUE))
RSB

2

මෙය කළ හැකි හොඳම ක්‍රමය වන්නේ වෙනත් .නෙට් අනුවාදයන් සමඟ අනුකූල වන අතර මෙය හැසිරවීමට සමාන හා ගෙට්හැෂ් අභිබවා යාමයි . නිර්නාමික වර්ගයකි ), නමුත් ඔබේ කේතය පුරාම සාමාන්‍ය දෙයක් ඔබට අවශ්‍ය නම්, මෙම ලිපියේ විසඳුම් විශිෂ්ටයි.


2

පාගාගෙන සමාන වේ (වස්තුව එය විවෘත) සහ GetHashCode () ක්රම:

class Person
{
    public int Id { get; set; }
    public int Name { get; set; }

    public override bool Equals(object obj)
    {
        return ((Person)obj).Id == Id;
        // or: 
        // var o = (Person)obj;
        // return o.Id == Id && o.Name == Name;
    }
    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }
}

ඉන්පසු අමතන්න:

List<Person> distinctList = new[] { person1, person2, person3 }.Distinct().ToList();

කෙසේ වෙතත් GetHashCode () වඩා දියුණු විය යුතුය (නම ද ගණන් කිරීමට), මෙම පිළිතුර මගේ මතය අනුව හොඳම වේ. ඇත්ත වශයෙන්ම, ඉලක්කගත තර්කනය සංරක්ෂණය කිරීම සඳහා, GetHashCode (), සමාන () අභිබවා යාමට අවශ්‍ය නැත, නමුත් අපට කාර්ය සාධනය අවශ්‍ය නම්, අපි එය අභිබවා යා යුතුය. සියලු සංසන්දනාත්මක ඇල්ගී, පළමුව හැෂ් පරීක්ෂා කරන්න, ඒවා සමාන නම් සමාන () අමතන්න.
ඔලෙග් ස්ක්‍රිප්නැක්

එසේම, සමාන () හි පළමු පේළිය "නම් (! (Obj යනු පුද්ගලයා)) වැරදියි" යන්නයි. නමුත් හොඳම පුරුද්ද වන්නේ "var o = obj person; if (o == null) false නම්;" වාත්තු නොකර o සමඟ සමානාත්මතාවය පරීක්ෂා කරන්න
Oleg Skripnyak

1
මේ හා සමානකම් ඉක්මවා යාම හොඳ අදහසක් නොවේ, මන්ද එය එක් දේපලකට වඩා පුද්ගලයාගේ සමානාත්මතාවය තීරණය කරනු ඇතැයි අපේක්ෂා කරන වෙනත් ක්‍රමලේඛකයින්ට අනපේක්ෂිත ප්‍රතිවිපාක ඇති කළ හැකිය.
බී 2 කේ

1
List<Person>lst=new List<Person>
        var result1 = lst.OrderByDescending(a => a.ID).Select(a =>new Player {ID=a.ID,Name=a.Name} ).Distinct();

Select() new Personඒ වෙනුවට ඔබ අදහස් කළේ new Player? ඔබ ඇණවුම් කරන IDකාරණය කෙසේ හෝ Distinct()අද්විතීය බව තීරණය කිරීමේදී එම දේපල භාවිතා කිරීමට දැනුම් දෙන්නේ නැත , එබැවින් මෙය ක්‍රියාත්මක නොවේ.
බේකන්

0

Person.id හි ඇත්ත වශයෙන්ම සමාන දේ කිරීමට ඔබට පුද්ගලයාට සමානකම් ඉක්මවා යා හැක. මෙය ඔබ අනුගමනය කරන හැසිරීමට හේතු විය යුතුය.


මම මෙම ප්‍රවේශය නිර්දේශ නොකරමි. මෙම විශේෂිත අවස්ථාවෙහිදී එය ක්‍රියාත්මක විය හැකි නමුත් එය හුදෙක් නරක පුරුද්දකි. ඔහුට වෙනත් තැනකින් වෙනත් දේපලකින් වෙන්කර හඳුනා ගැනීමට අවශ්‍ය නම් කුමක් කළ යුතුද? ඔහුට සමානව දෙවරක් අභිබවා යා නොහැකි බව ඔහුට විශ්වාසද? :-) ඒ හැරුණු විට, වස්තු දෙකක් සමානද නැද්ද යන්න කීමට අදහස් කරන බැවින්, මේ සඳහා සමානකම් ඉක්මවා යාම මූලික වශයෙන් වැරදිය. කිසියම් හේතුවක් නිසා සමානාත්මතාවය සඳහා පන්ති තත්ත්වය වෙනස් වුවහොත්, ඔබ නියත වශයෙන්ම ඔබේ ඇඟිලි පුළුස්සා දමනු ඇත ...
ඇලන්

-5

කරුණාකර පහත කේතය සමඟ උත්සාහ කරන්න.

var Item = GetAll().GroupBy(x => x .Id).ToList();

3
කෙටි පිළිතුරක් සාදරයෙන් පිළිගනිමු, කෙසේ වෙතත් ගැටළුව පිටුපස සිදුවන්නේ කුමක්ද යන්න තේරුම් ගැනීමට උත්සාහ කරන පසුකාලීන පරිශීලකයින්ට එය වැඩි වටිනාකමක් ලබා නොදේ. ගැටලුව ඇතිවීමට ඇති සැබෑ ගැටළුව කුමක්ද සහ විසඳන්නේ කෙසේද යන්න පැහැදිලි කිරීමට කරුණාකර යම් කාලයක් ඉතිරි කරන්න. ස්තූතියි ~
හෙරන්
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.