Как отфильтровать общий список <> с объектом того же класса - PullRequest
1 голос
/ 08 июня 2009

Я искал интернет для этого ответа и спросил нескольких разработчиков, и у меня не получилось. У меня есть класс с именем StaffingPositionsDataContract, который я загружаю фиктивные данные (пока) в список <> и возвращаюсь на страницу. Это прекрасно работает, но теперь мне нужно отфильтровать список на основе другого списка значений, которые вводятся на экране, отправить в этот сервис как JSON, а затем десериализовать в список того же класса. Обратите внимание, что пользователь может фильтровать по любому из этих членов класса, поэтому все могут быть нулевыми, или один может быть нулевым и т. Д. Вот метод обслуживания:

   public List<StaffingPositionsDataContract> GetStaffingPosition(string searchFilters)
    {
        var filters = JsonConvert.DeserializeObject<List<StaffingPositionsDataContract>>(searchFilters);
        IList<StaffingPositionsDataContract> contracts = new StaffingPositionsDataContract().LoadMockData();

        if (searchFilters.Length > 4)
        {
            //Filter contracts here!
        }

        return contracts;
    }

Вот класс данных контракта с фиктивными данными для загрузки:

[DataContract] [Serializable]
public class StaffingPositionsDataContract
{
    [DataMember(Order = 1)] public int PositionId { get; set; }
    [DataMember(Order = 2)] public string Series { get; set; }
    [DataMember(Order = 3)] public string BFY { get; set; }
    [DataMember(Order = 4)] public string BudgetStatus { get; set; }
    [DataMember(Order = 5)] public string DutyStation { get; set; }
    [DataMember(Order = 6)] public string OrgLocation { get; set; }
    [DataMember(Order = 7)] public string BudgetingEntity { get; set; }
    [DataMember(Order = 8)] public string SeriesTitle { get; set; }
    [DataMember(Order = 9)] public int PersonnelId { get; set; }
    [DataMember(Order = 10)] public string PositionStatus { get; set; }
    [DataMember] public int RecId { get; set; }

    public List<StaffingPositionsDataContract> LoadMockData()
    {
        List<StaffingPositionsDataContract> staffingposition = new List<StaffingPositionsDataContract>()
        {
            new StaffingPositionsDataContract() {RecId=1, PositionId = 12345, Series="", BFY="FY2010", BudgetStatus="Actual", DutyStation="", OrgLocation="", BudgetingEntity=""},
            new StaffingPositionsDataContract() {RecId=2, PositionId = 67891, Series="", BFY="FY2011", BudgetStatus="Actual", DutyStation="", OrgLocation="", BudgetingEntity=""},
            new StaffingPositionsDataContract() {RecId=3,PositionId = 12345, Series="", BFY="FY2010", BudgetStatus="Projected", DutyStation="", OrgLocation="", BudgetingEntity=""},
            new StaffingPositionsDataContract() {RecId=4,PositionId = 67892, Series="", BFY="FY2011", BudgetStatus="Projected", DutyStation="", OrgLocation="", BudgetingEntity=""},
            new StaffingPositionsDataContract() {RecId=5,PositionId = 987654, Series="", BFY="FY2010", BudgetStatus="Projected", DutyStation="", OrgLocation="", BudgetingEntity=""}
        };
        return staffingposition;
    }
}

Обратите внимание, что фильтры всегда будут списком из одного, нескольких или всех заполняемых значений. Пожалуйста, сохраните мое здравомыслие и помогите, если сможете! СПАСИБО!

Я должен был отметить ранее, что ДЕЙСТВИТЕЛЬНО хочу, чтобы это была универсальная функция, которая может использоваться любым из этих похожих классов данных (их много).

Ответы [ 3 ]

1 голос
/ 08 июня 2009

Я бы не фильтровал, где вы фильтруете. Я бы передал фильтр загрузке коллекции и использовал его внутри себя, передав эти критерии в службу, базу данных или тому подобное, или заставляя каждый объект проверять себя в соответствии с критериями перед добавлением его в коллекцию.

public List<StaffingPositionsDataContract> GetStaffingPosition(string searchFilters)
{
    var filters = JsonConvert.DeserializeObject<List<StaffingPositionsDataContract>>(searchFilters);
    IList<StaffingPositionsDataContract> contracts = new StaffingPositionsDataContract().LoadMockData(searchFilters);

    return contracts;
}

[DataContract] [Serializable]
public class StaffingPositionsDataContract
{
    [DataMember(Order = 1)] public int PositionId { get; set; }
    [DataMember(Order = 2)] public string Series { get; set; }
    [DataMember(Order = 3)] public string BFY { get; set; }
    [DataMember(Order = 4)] public string BudgetStatus { get; set; }
    [DataMember(Order = 5)] public string DutyStation { get; set; }
    [DataMember(Order = 6)] public string OrgLocation { get; set; }
    [DataMember(Order = 7)] public string BudgetingEntity { get; set; }
    [DataMember(Order = 8)] public string SeriesTitle { get; set; }
    [DataMember(Order = 9)] public int PersonnelId { get; set; }
    [DataMember(Order = 10)] public string PositionStatus { get; set; }
    [DataMember] public int RecId { get; set; }

    public List<StaffingPositionsDataContract> LoadMockData(string searchfilters)
    {
        // filter the list returned here

        List<StaffingPositionsDataContract> staffingposition = new List<StaffingPositionsDataContract>()
        {
            new StaffingPositionsDataContract() {RecId=1, PositionId = 12345, Series="", BFY="FY2010", BudgetStatus="Actual", DutyStation="", OrgLocation="", BudgetingEntity=""},
            new StaffingPositionsDataContract() {RecId=2, PositionId = 67891, Series="", BFY="FY2011", BudgetStatus="Actual", DutyStation="", OrgLocation="", BudgetingEntity=""},
            new StaffingPositionsDataContract() {RecId=3,PositionId = 12345, Series="", BFY="FY2010", BudgetStatus="Projected", DutyStation="", OrgLocation="", BudgetingEntity=""},
            new StaffingPositionsDataContract() {RecId=4,PositionId = 67892, Series="", BFY="FY2011", BudgetStatus="Projected", DutyStation="", OrgLocation="", BudgetingEntity=""},
            new StaffingPositionsDataContract() {RecId=5,PositionId = 987654, Series="", BFY="FY2010", BudgetStatus="Projected", DutyStation="", OrgLocation="", BudgetingEntity=""}
        };
        return staffingposition;
    }
}
0 голосов
/ 08 июня 2009

Отправьте элементы обеих коллекций в XElements, сделав каждое свойство XAttribute.

Затем вы можете сравнить атрибуты, чтобы найти совпадения, что просто.

public class Customer
{
    public int CustomerId { get; set; }
    public string Name { get; set; }
    public string FavoriteColor { get; set; }

    // probably a better way to do this
    // just writing fast for demo
    public XElement ToXElement()
    {
        List<XAttribute> attributes = new List<XAttribute>();

        if (this.CustomerId != 0)
            attributes.Add(new XAttribute("CustomerId", this.CustomerId));
        if (this.Name != null)
            attributes.Add(new XAttribute("Name", this.Name));
        if (this.FavoriteColor != null)
            attributes.Add(new XAttribute("FavoriteColor", this.FavoriteColor));

        XElement result = new XElement("Customer", attributes);
        return result;
    }
}

Тогда сравнивать их ....

List<Customer> source = new List<Customer>()
{ new Customer(){ CustomerId=1, FavoriteColor="Blue", Name="Alex" },
  new Customer(){ CustomerId=2, FavoriteColor="Green", Name="Bob" },
  new Customer(){ CustomerId=3, FavoriteColor="Blue", Name="Cindy" },
  new Customer(){ CustomerId=4, FavoriteColor="Red", Name="Darren" }
};
List<Customer> examples = new List<Customer>()
{ new Customer(){ FavoriteColor="Blue", CustomerId = 3},
  new Customer(){ Name="Darren"}
};

List<XElement> sourceElements = source.Select(c => c.ToXElement()).ToList();
List<XElement> exampleElements = examples.Select(c => c.ToXElement()).ToList();

//and now the query...
var query = sourceElements
  .Where(s => exampleElements
    .Any(ex => ex.Attributes()
      .All(exatt => s.Attribute(exatt.Name).Value == exatt.Value)
    )
  );

foreach(XElement x in query)
  Console.WriteLine(x);

Также:

  • Если вы отправите в одном пустом примере (все значения по умолчанию), вы получите весь список источников.
  • Если вы не отправите ни одного примера (пустой список), вы ничего не получите.
0 голосов
/ 08 июня 2009

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

Фильтрация одного списка с другим довольно проста с Linq:

var foo = new int[]{1,2,3,4,5};
var bar = new int[]{1,3,5};
var result = from x in foo where !bar.Contains(x) select x;

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

Если ваш пользовательский интерфейс позволяет пользователям «создавать» от 1 до n контрактов для фильтрации, и вы получаете это как набор контрактов (ни один из которых не может быть нулевым), это все равно будет работать.


В ответ на комментарий Захо:

var foo = new string[]{"1","2","3","4","5"}; 
var bar = new string[]{"1","3",null,"5"};
var result = from x in foo where !bar.Contains(x) select x;

Фильтр enumerable - bar - содержит нули. Эта функция работает. Если это решение не работает для вас, Зако, у вас другая проблема. Полагаю, это как-то связано со сравнениями на равенство.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...