Как пропустить добавление дублирующего ключа в словарь с помощью linq в c # [duplicate]

Другое решение состоит в том, чтобы выполнить код через последовательный исполнитель nsynjs .

Если базовая функция многозначна

nsynjs будет последовательно оценивать все обещания и ставить обещания результат в свойство data:

function synchronousCode() {

    var getURL = function(url) {
        return window.fetch(url).data.text().data;
    };
    
    var url = 'https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js';
    console.log('received bytes:',getURL(url).length);
    
};

nsynjs.run(synchronousCode,{},function(){
    console.log('synchronousCode done');
});

Если базовая функция не обещает

Шаг 1. Wrap с обратным вызовом в оболочку, совместимую с nsynjs (если у нее есть обещанная версия, вы можете пропустить этот тест):

var ajaxGet = function (ctx,url) {
    var res = {};
    var ex;
    $.ajax(url)
    .done(function (data) {
        res.data = data;
    })
    .fail(function(e) {
        ex = e;
    })
    .always(function() {
        ctx.resume(ex);
    });
    return res;
};
ajaxGet.nsynjsHasCallback = true;

Шаг 2. Вставить синхронную логику в функцию:

function process() {
    console.log('got data:', ajaxGet(nsynjsCtx, "data/file1.json").data);
}

Шаг 3. Выполнить функцию синхронно через nnsynjs:

nsynjs.run(process,this,function () {
    console.log("synchronous function finished");
});

Nsynjs будет оценивать все операторы и выражения шаг за шагом, приостанавливая выполнение в случае, если результат некоторой медленной функции не готов.

Дополнительные примеры здесь: https://github.com/amaksr/nsynjs/tree/master/examples

115
задан BartoszKP 27 September 2013 в 15:55
поделиться

9 ответов

Вот очевидное, не linq решение:

foreach(var person in personList)
{
  if(!myDictionary.Keys.Contains(person.FirstAndLastName))
    myDictionary.Add(person.FirstAndLastName, person);
}
50
ответ дан Carra 5 September 2018 в 11:10
поделиться

Чтобы справиться с устранением дубликатов, используйте 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);
7
ответ дан Anthony Pegram 5 September 2018 в 11:10
поделиться

Начиная с решения Carra вы также можете записать его как:

foreach(var person in personList.Where(el => !myDictionary.ContainsKey(el.FirstAndLastName)))
{
    myDictionary.Add(person.FirstAndLastName, person);
}
0
ответ дан Cinquo 5 September 2018 в 11:10
поделиться

Вы также можете использовать функцию ToLookup LINQ, которую вы можете использовать почти взаимозаменяемо с помощью словаря.

_people = personList
    .ToLookup(e => e.FirstandLastName, StringComparer.OrdinalIgnoreCase);
_people.ToDictionary(kl => kl.Key, kl => kl.First()); // Potentially unnecessary

Это будет по существу делать GroupBy в ответе LukeH , но даст хеширование, предоставляемое Словарем. Таким образом, вам, вероятно, не нужно преобразовывать его в словарь, но просто используйте функцию LINQ First, когда вам нужно получить доступ к значению для ключа.

7
ответ дан Community 5 September 2018 в 11:10
поделиться

Вы можете создать метод расширения, подобный 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; 
    }

В этом случае, если есть дубликаты, то выигрывает последнее значение.

5
ответ дан Eric 5 September 2018 в 11:10
поделиться
        DataTable DT = new DataTable();
        DT.Columns.Add("first", typeof(string));
        DT.Columns.Add("second", typeof(string));

        DT.Rows.Add("ss", "test1");
        DT.Rows.Add("sss", "test2");
        DT.Rows.Add("sys", "test3");
        DT.Rows.Add("ss", "test4");
        DT.Rows.Add("ss", "test5");
        DT.Rows.Add("sts", "test6");

        var dr = DT.AsEnumerable().GroupBy(S => S.Field<string>("first")).Select(S => S.First()).
            Select(S => new KeyValuePair<string, string>(S.Field<string>("first"), S.Field<string>("second"))).
           ToDictionary(S => S.Key, T => T.Value);

        foreach (var item in dr)
        {
            Console.WriteLine(item.Key + "-" + item.Value);
        }
2
ответ дан King 5 September 2018 в 11:10
поделиться

Это должно работать с лямбда-выражением:

personList.Distinct().ToDictionary(i => i.FirstandLastName, i => i);
22
ответ дан Luc Wollants 5 September 2018 в 11:10
поделиться

Решение 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;
}
328
ответ дан Ryan 5 September 2018 в 11:10
поделиться

Linq-решение с использованием Distinct () и без группировки:

var _people = personList
    .Select(item => new { Key = item.Key, FirstAndLastName = item.FirstAndLastName })
    .Distinct()
    .ToDictionary(item => item.Key, item => item.FirstFirstAndLastName, StringComparer.OrdinalIgnoreCase);

Я не знаю, хорош ли это, чем решение LukeH, но оно также работает.

34
ответ дан Tillito 5 September 2018 в 11:10
поделиться
Другие вопросы по тегам:

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