Person 객체 목록이 있습니다. 키가 성과 이름 (연결)이고 값이 Person 객체 인 Dictionary로 변환하고 싶습니다.
문제는 중복 된 사람들이 있다는 것이므로이 코드를 사용하면 문제가 발생합니다.
private Dictionary<string, Person> _people = new Dictionary<string, Person>();
_people = personList.ToDictionary(
e => e.FirstandLastName,
StringComparer.OrdinalIgnoreCase);
나는 그것이 이상하게 들린다는 것을 알고 있지만 실제로는 중복 이름에 관심이 없습니다. 이름이 여러 개인 경우 하나만 잡고 싶습니다. 어쨌든이 코드를 작성할 수 있습니까? 그래서 이름 중 하나만 사용하고 복제본을 날려 버리지 않습니다.
답변
linq가 아닌 명백한 솔루션은 다음과 같습니다.
foreach(var person in personList)
{
if(!myDictionary.Keys.Contains(person.FirstAndLastName))
myDictionary.Add(person.FirstAndLastName, person);
}
답변
LINQ 솔루션 :
// Use the first value in group
var _people = personList
.GroupBy(p => p.FirstandLastName, StringComparer.OrdinalIgnoreCase)
.ToDictionary(g => g.Key, g => g.First(), StringComparer.OrdinalIgnoreCase);
// Use the last value in group
var _people = personList
.GroupBy(p => p.FirstandLastName, StringComparer.OrdinalIgnoreCase)
.ToDictionary(g => g.Key, g => g.Last(), StringComparer.OrdinalIgnoreCase);
LINQ 이외의 솔루션을 선호하는 경우 다음과 같이 할 수 있습니다.
// Use the first value in list
var _people = new Dictionary<string, Person>(StringComparer.OrdinalIgnoreCase);
foreach (var p in personList)
{
if (!_people.ContainsKey(p.FirstandLastName))
_people[p.FirstandLastName] = p;
}
// Use the last value in list
var _people = new Dictionary<string, Person>(StringComparer.OrdinalIgnoreCase);
foreach (var p in personList)
{
_people[p.FirstandLastName] = p;
}
답변
Distinct ()를 사용하고 그룹화하지 않은 Linq 솔루션은 다음과 같습니다.
var _people = personList
.Select(item => new { Key = item.Key, FirstAndLastName = item.FirstAndLastName })
.Distinct()
.ToDictionary(item => item.Key, item => item.FirstFirstAndLastName, StringComparer.OrdinalIgnoreCase);
그것이 LukeH의 솔루션보다 좋은지 모르겠지만 잘 작동합니다.
답변
이것은 람다 식과 함께 작동해야합니다.
personList.Distinct().ToDictionary(i => i.FirstandLastName, i => i);
답변
당신은 또한 사용할 수 있습니다 ToLookup
당신은 다음 사전과 거의 같은 의미로 사용할 수 있습니다 LINQ의 기능을.
_people = personList
.ToLookup(e => e.FirstandLastName, StringComparer.OrdinalIgnoreCase);
_people.ToDictionary(kl => kl.Key, kl => kl.First()); // Potentially unnecessary
이것은 본질적으로 LukeH의 답변 에서 GroupBy를 수행 하지만 Dictionary가 제공하는 해싱을 제공합니다. 따라서 사전으로 변환 할 필요는 없지만 First
키 값에 액세스해야 할 때마다 LINQ 함수를 사용하십시오 .
답변
중복을 허용한다는 차이점을 가지고 ToDictionary ()와 유사한 확장 메소드를 작성할 수 있습니다. 다음과 같은 것 :
public static Dictionary<TKey, TElement> SafeToDictionary<TSource, TKey, TElement>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector,
IEqualityComparer<TKey> comparer = null)
{
var dictionary = new Dictionary<TKey, TElement>(comparer);
if (source == null)
{
return dictionary;
}
foreach (TSource element in source)
{
dictionary[keySelector(element)] = elementSelector(element);
}
return dictionary;
}
이 경우 중복이 있으면 마지막 값이 이깁니다.
답변
중복 제거를 처리하려면 메소드 IEqualityComparer<Person>
에서 사용할 수 있는 것을 구현 한 Distinct()
다음 사전을 얻는 것이 쉬울 것입니다. 주어진:
class PersonComparer : IEqualityComparer<Person>
{
public bool Equals(Person x, Person y)
{
return x.FirstAndLastName.Equals(y.FirstAndLastName, StringComparison.OrdinalIgnoreCase);
}
public int GetHashCode(Person obj)
{
return obj.FirstAndLastName.ToUpper().GetHashCode();
}
}
class Person
{
public string FirstAndLastName { get; set; }
}
사전을 얻으십시오 :
List<Person> people = new List<Person>()
{
new Person() { FirstAndLastName = "Bob Sanders" },
new Person() { FirstAndLastName = "Bob Sanders" },
new Person() { FirstAndLastName = "Jane Thomas" }
};
Dictionary<string, Person> dictionary =
people.Distinct(new PersonComparer()).ToDictionary(p => p.FirstAndLastName, p => p);