В поисках лучшего способа извлечь все типы данных и подготовить словарь с типом данных в качестве ключа и списком фильтров в качестве значения - PullRequest
0 голосов
/ 19 марта 2020

У меня ниже структура класса и список CollectionInstance

public class CollectionInstance
{
    public string Name { get; set; }
    public List<CollectionProperty> CollectionProperties { get; set; }
}

public class CollectionProperty
{
    public string Name { get; set; }
    public object Value { get; set; }
    public string DataType { get; set; }
}

Вот список CollectionInstance. В настоящее время у него есть только два типа данных: double и string, но у меня есть больше типов данных

var lstCollectionInstances = new List<CollectionInstance>
        {
            new CollectionInstance
            {
                Name = "A",
                CollectionProperties = new List<CollectionProperty>
                {
                    new CollectionProperty {Name = "P1", Value = 10, DataType = "Double"}
                }
            },
            new CollectionInstance
            {
                Name = "A",
                CollectionProperties = new List<CollectionProperty>
                {
                    new CollectionProperty {Name = "P2", Value = "H1", DataType = "String"}
                }
            },
            new CollectionInstance
            {
                Name = "B",
                CollectionProperties = new List<CollectionProperty>
                {
                    new CollectionProperty {Name = "P1", Value = 20, DataType = "Double"}
                }
            },
            new CollectionInstance
            {
                Name = "B",
                CollectionProperties = new List<CollectionProperty>
                {
                    new CollectionProperty {Name = "P2", Value = "H2", DataType = "String"}
                }
            },
        };

Теперь моя цель - выбрать все различные типы данных и список фильтров CollectionInstance в зависимости от типа данных. Может быть словарём или другой коллекцией, где я должен хранить тип данных как ключ и фильтровать CollectionInstance как значение.

Я попробовал ниже, но что может быть лучшим способом?

var dictionary = new Dictionary<string, List<CollectionInstance>>();

        var dataTypesGroups = lstCollectionInstances
            .SelectMany(x => x.CollectionProperties).GroupBy(x => x.DataType);

        foreach (var dataType in dataTypesGroups)
        {
            dictionary.Add(dataType.Key, GetFilterData(lstCollectionInstances, dataType.Key));
        }


private static List<CollectionInstance> GetFilterData(IEnumerable<CollectionInstance> lst, string dataType)
    {
        return lst.Where(x => x.CollectionProperties.Any(y => y.DataType == dataType)).ToList();
    }

Ответы [ 3 ]

1 голос
/ 19 марта 2020

Вы можете сохранить ссылку на родителя CollectionInstance при группировке и использовать ее при выборе результатов:

lstCollectionInstances
        .SelectMany(x => x.CollectionProperties, (i, c) => new {CollectionInstance = i, CollectionProperty = c})
        .GroupBy(x => x.CollectionProperty.DataType)
        .ToDictionary(c => c.Key, c => c.Select(d => d.CollectionInstance) )

UPD здесь мы используем эту перегрузку .SelectMany(). Таким образом, вместо List<CollectionProperty> вы получите List<Tuple<CollectionInstance,CollectionProperty>> (ну, я выбрал анонимный тип, но это не имеет большого значения) . Вы в основном улучшаете каждый дочерний объект со ссылкой на его родителя. И поскольку все это просто ссылки - вы не торгуете большим количеством памяти, чтобы иметь его. И когда вы группируете его - вы получаете возможность не выбирать CollectionProperty, а непосредственно родительский объект.

Надеюсь, это имеет смысл

1 голос
/ 19 марта 2020

Лично считаю, что использование LINQ делает его более нечитаемым и трудным для понимания. Это в основном операция с двумя l oop; for each x in instances/foreach y in x.properties/add x to dictionary indexed by y.z и было бы легче понять, сохранив его как таковой. Это сводит к минимуму объем работы, выполняемой платформой; здесь мы не создаем ненужных дополнительных объектов, списков, группировок и т. д. c, чтобы перечислить иерархию объектов глубиной 2 и создать словарь, и даже кодер, который никогда не видел LINQ, может это понять:

    var dictionary = new Dictionary<string, List<CollectionInstance>>();

    foreach (var ci in lstCollectionInstances){
        foreach(var cp in ci.CollectionProperties){
            if(!dictionary.ContainsKey(cp.DataType))
                dictionary[cp.Key] = new List<CollectionInstance>();
            dictionary[cp.Key].Add(ci);
        }
    }

LINQ - молоток; не каждая проблема это гвоздь

1 голос
/ 19 марта 2020

Создание словаря, в котором для каждого типа данных хранится список экземпляров со свойством типа данных ключа.

var result = instances
    .SelectMany(x => x.Properties)
    .Select(x => x.DataType)
    .Distict()
    .ToDictionary(x => x, x => GetInstancesWithPropertyOfType(x, instances));

При условии определения следующего:

public class Instance
{
    public string Name { get; set; }
    public List<Property> Properties { get; set; }
}

public class Property
{
    public string Name { get; set; }
    public object Value { get; set; }
    public string DataType { get; set; }
}

List<Instance> GetInstancesWithPropertyOfType(string dataType, IEnumerable<Instance> instances) => 
    instances.Where(x => x.Properties.Any(y => y.DataType == dataType)).ToList();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...