Найти, находится ли элемент в одном IEnumerable также в другом IEnumerable - PullRequest
1 голос
/ 21 октября 2010

У меня есть 2 IEnumerable из Type1 и Type2 , т.е. IEnumerable<Type1> & IEnumerable<Type2>. Type1 и Type2 имеют 1 общее поле, которое называется TypeID . Множество одинаковых TypeID может существовать в IEnumerable<Type2>, я хотел бы проверить по 2 IEnumerables и если TypeID внутри Type2 равно TypeID внутри Тип1 , я бы объединил 2 в новый объект. Если это не так, то для нового объекта просто установите IEnumerable<Type2> как null. Это немного сбивает с толку, поэтому я включил псевдокод, чтобы лучше продемонстрировать, что я пытаюсь достичь:

namespace test
{
    public class ConfigMetaDataColumns
    {
        public int FieldID { get { return ValueInt("FieldID"); } }
        public string Label { get { return ValueString("Label"); } }
        public string FieldName { get { return ValueString("FieldName"); } }
    }

    public class ConfigDataColumns
    {
        public int FieldID { get { return ValueInt("FieldID"); } }
        public double NumericValue { get { return ValueDouble("NumericValue"); } }
    }

    public class ConfigMetaDataCombinedColumns
    {
        public ConfigMetaDataColumns ConfigMetaData { get; set; }
        public IEnumerable<ConfigDataColumns> ConfigData { get; set; }
    }

    public class GetCombinedData
    {
        // Get ConfigMetaData
        private IEnumerable<ConfigMetaDataColumns> GetConfigMetaData()
        {
            var requester = GetConfigMetaDataMethodHere();
            return requester.Items;
        }

        // Get ConfigMeta
        private IEnumerable<ConfigMetaDataColumns> GetConfigMetaData()
        {
            var requester = GetConfigDataMethodHere();
            return requester.Items;
        }

        // Combine the two here!
        private IEnumerable<ConfigMetaDataCombinedColumns> GetData()
        {
            /*
             * ConfigMetaDataColumns example:
             * FieldID:     1
             * Label:       Label1
             * FieldName:   FieldName1
             * 
             * FieldID:     2
             * Label:       Label2
             * FieldName:   FieldName2
             * 
             * FieldID:     3
             * Label:       Label3
             * FieldName:   FieldName3
             * */

            /*
             * ConfigDataColumns example:
             * FieldID:     1
             * NumericVal:  NumericVal1

             * FieldID:     1
             * NumericVal:  NumericVal2

             * FieldID:     3
             * NumericVal:  NumericVal3
             * */

            /*
             * Cobined data should be:
             * 
             * FieldID:     1
             * Label:       Label1
             * FieldName:   FieldName1
             {* FieldID:    1
             * NumericVal:  NumericVal1
             * FieldID:     1
             * NumericVal:  NumericVal2}
             * 
             * FieldID:     2
             * Label:       Label2
             * FieldName:   FieldName2
             {* NULL *}
             * 
             * FieldID:     3
             * Label:       Label3
             * FieldName:   FieldName3
             {* FieldID:    3
             * NumericVal:  NumericVal3}
             * */
        }
    }
}

Спасибо.

Ответы [ 4 ]

3 голосов
/ 22 октября 2010

Если я правильно прочитал ваш вопрос, все, что вам нужно, по сути, это левое соединение.

Пример:

class Foo
{
    public int SomeId { get; set; }
}

class Bar
{
    public int SomeId { get; set; }
}

class FooWithBars
{
    public Foo Foo { get; set; }
    public IEnumerable<Bar> Bars { get; set; }
}

...

List<Foo> foos = new List<Foo>();
List<Bar> bars = new List<Bar>();

foos.Add(new Foo() { SomeId = 1 });
foos.Add(new Foo() { SomeId = 2 });

bars.Add(new Bar() { SomeId = 1 });
bars.Add(new Bar() { SomeId = 1 });

// get all foos and matching bars
var combined = from foo in foos
                join bar in bars
                on foo.SomeId equals bar.SomeId into g
                select new FooWithBars
                {
                    Foo = foo,
                    Bars = g.Any() ? g : null
                };

В этом примере вы получаете IEnumerable<Bar> или ноль, согласно вашему требованию.

0 голосов
/ 22 октября 2010

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

IEnumerable<ConfigMetaDataCombinedColumns> combined =
    GetConfigMetaData()
    .Select(p=> new ConfigMetaDataCombinedColumns() {ConfigMetaData = p
        , ConfigData = GetConfigData().Where(q=>q.FieldID == p.FieldID)  });
0 голосов
/ 22 октября 2010

Я полагаю, что соединение с ResultSelector, вызывающее ваш метод GetData, но передающее объекты в качестве аргументов, будет работать для вас.

//IEnumerable<Type1> List1
//IEnumerable<Type2> List2

var result = List1.Join( List2, a => a.TypeId, b => b.TypeId, (a, b) => GetData(a, b));
//do something with result
0 голосов
/ 22 октября 2010

Полное предположение ... но я думаю, это то, что вы хотите:

private IEnumerable<ConfigMetaDataCombinedColumns> ReturnMe()
{
   var query = from meta in GetConfigMetaData().AsQueryable()
            join data in GetConfigDataColumns().AsQueryable()
            on meta.FieldID equals data.FieldID
            select new {
                ConfigMetaDataColumns = meta,
                ConfigDataColumns = data
            };
   return  from item in query
            group item by item.ConfigMetaDataColumns into l 
            select new ConfigMetaDataCombinedColumns()
            {
                ConfigMetaData = l.Key,
                ConfigData = l.Select(x=>x.ConfigDataColumns)

            }        ;
}
...