Nano Hash - криптовалюты, майнинг, программирование

Запрос LINQ не может идентифицировать дубликаты

У меня есть два пользовательских класса.

Первый класс содержит основные данные:

public class Request
{
    public Request(int lineID, string partNo, int qty, int reasonID, int typeID)
    {
        LineID = lineID;
        PartNo = partNo;
        Qty = qty;
        ReasonID = reasonID;
        TypeID = typeID;
    }
    public int LineID { get; private set; }
    public string PartNo { get; private set; }
    public int Qty { get; internal set; }
    public int ReasonID { get; private set; }
    public int TypeID { get; private set; }
}

Второй класс содержит список этих объектов запроса со следующей подписью:

public class Requests : IEnumerable<Request>
{
    private List<Request> list;

    public Requests()
    {
        list = new List<Request>();
    }

    public int Add(Request item)
    {
        if (item != null)
        {
            foreach (var x in list.Where(r => 
              (r.LineID == item.LineID) &&
              (r.PartNo == item.PartNo) &&
              (r.ReasonID == item.ReasonID) &&
              (r.TypeID == item.TypeID)))
            {
                x.Qty += item.Qty;
                return list.IndexOf(x);
            }
            list.Add(item);
            return list.Count - 1;
        }
        return -1;
    }

    // other code 
}

Я тестирую свой код, и добавление элементов добавляет новые элементы в список, но запрос LINQ для поиска дубликатов не работает.

Если в список добавляются 2 одинаковых элемента, я хочу, чтобы мой код был достаточно умным, чтобы просто обновлять количество, но, похоже, он не работает.

Может ли кто-нибудь сказать мне, что не так с запросом LINQ?


  • Что такое RequestId? Он не определен в вашем классе. 14.06.2012
  • Не ответ, но использование foreach бессмысленно, так как вы возвращаетесь на первой итерации. 14.06.2012
  • @JoelPotter Глядя на код, я бы предположил, что OP либо новичок в LINQ, либо не использует его очень часто. 14.06.2012
  • Я бы заставил Request реализовать IEquatable‹Request› и использовать list.Contains(item)... 14.06.2012
  • Джон: Я не показывал очень длинный, полный класс. Это была опечатка, которую я исправил. Извинения. Другие: Да, я новичок в LINQ. Рафаэль: Значение количества (Qty) будет варьироваться для разных элементов. 14.06.2012
  • @ jp2code, код выглядит так, как будто он должен работать так, как вы хотите. Можете ли вы обновить свой вопрос, чтобы показать нам несколько строк кода, который использует ваш метод и демонстрирует проблему? 14.06.2012
  • Относительно сложно следить за тем, что происходит. Короткая, но полная программа, демонстрирующая проблему, действительно поможет. 14.06.2012
  • @KirkWoll: я не знаю, как это сделать. Код моего веб-приложения просто добавляет элемент в класс Requests. У меня установлена ​​точка останова в этом месте, и когда я вхожу в нее, все значения выглядят равными. 14.06.2012
  • @ jp2code, но это не похоже на проблему с веб-приложением. Как предложил Джон, вы не можете создать простое консольное приложение, которое вызывает метод Add и передает ему дубликат и воспроизводит его таким образом? Если это так, вы можете опубликовать этот код, и мы могли бы попробовать его. 14.06.2012
  • @ jp2code Ваша реализация не очень хороша, но логически правильна. Я бы посмотрел на использование класса Requests. Вы уверены, что используете один и тот же экземпляр Requests между неудачными случаями? Потому что если вы этого не сделаете, вы каждый раз будете работать над новым списком... 14.06.2012
  • @RaphaëlAlthaus Первоначально я думал об этом (часто случается с веб-формами), но отклонял его всякий раз, когда отладчик показывал элементы в моем списке, которые были равны, но все еще не попадали в метод x.Qty += item.Qty ... но LINQ делает некоторые странные вещи в отладчик, так что вы можете быть правы. Я хотел бы увидеть гораздо более красивый способ достижения моей цели. Мое консольное приложение, тестирующее это, отлично работает, кстати. 14.06.2012
  • @ jp2code, вы можете установить точку останова внутри вашей лямбды (после r =>). Если вы сделаете это, вы сможете сравнить свойство за свойством и понять, почему оно не возвращает значение true. 14.06.2012

Ответы:


1

Может ли кто-нибудь сказать мне, что не так с запросом LINQ?

Теоретически выглядит нормально. Думаю, нам нужно больше информации о ваших данных, чтобы понять, почему они работают не так, как вы ожидаете. Является ли комбинация LineID, PartNo, ReasonID и TypeID уникальным отличием элемента? Поскольку PartNo является строкой, значения не чувствительны к регистру (ваше сравнение учитывает регистр)?

Если в список добавляются 2 одинаковых элемента, я хочу, чтобы мой код был достаточно умным, чтобы просто обновлять количество, но, похоже, он не работает.

Для этого я бы предложил другой подход. Рассмотрите возможность переопределения Equals() для вашего типа Request. Затем ваш метод Add может просто проверить, содержит ли список элемент, увеличивая количество, если да, и добавляя его, если нет:

var idx = list.IndexOf(item);
if(idx != -1)
{
    list[idx].Qty += item.Qty;
}
else
{
    list.Add(item);
}
14.06.2012

2

Заставьте Request реализовать IEquatable<Request>, потому что это то, что использует IndexOf:

public bool Equals(Request other) {
    return other != null && (this.LineID == other.LineID) && (this.PartNo == other.PartNo) && (this.ReasonID == other.ReasonID) && (this.TypeID == other.TypeID);
}

Затем:

public int Add(Request item) {
    if (item != null)
    {
        int ind = list.IndexOf(item);

        if (ind == -1)
        {
            list.Add(item);
            return list.Count - 1;
        }
        else
        {
            list[ind].Qty += item.Qty;
            return ind;
        }                
    }
    return -1;
}
14.06.2012

3

Вы можете изменить метод, материализовав запрос LINQ. Например:

public int Add(Request item) {
    if (item != null) {
      foreach (var x in list.Where(r => 
        (r.LineID == item.LineID) &&
        (r.PartNo == item.PartNo) &&
        (r.ReasonID == item.ReasonID) &&
        (r.TypeID == item.TypeID)
        ).ToList()) {
        x.Qty += item.Qty;
        return list.IndexOf(x);
      }
      list.Add(item);
      return list.Count - 1;
    }
    return -1;
  }

Но, поскольку ваши запросы должны быть уникальными, вы можете использовать это

public int Add(Request item)
{
    if (item != null)
    {
        var req = list.SingleOrDefault(r =>
                              (r.LineID == item.LineID) &&
                              (r.PartNo == item.PartNo) &&
                              (r.ReasonID == item.ReasonID) &&
                              (r.TypeID == item.TypeID)
            );
        if(req!=null)
        {
            req.Qty += item.Qty;
            return list.IndexOf(req);
        }
        list.Add(item);
        return list.Count - 1;
    }
    return -1;
}
14.06.2012
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..