Как сгруппировать список кортежей из 3 элементов, где element.item3 == element2.item2 - PullRequest
1 голос
/ 27 июня 2019

У меня следующая проблема: Нужно сгруппировать List<Tuple<object, int, int>>, где item3 равен item2 для различных элементов, и если есть элементы, которые не совпадают, они должны оставаться в текущей позиции! Чтобы быть более конкретным List<Tuple<UserDescription, userId, inviterId>>

Я пробовал разные способы с LINQ - группировать, выбирать, где, но безуспешно ....

var list = new List<Tuple<object, int, int>> // item2 - UserId, item3 - InviterId
    {
        new Tuple<object, int, int>(new { Name = "Ivan" }, 1, 12),
        new Tuple<object, int, int>(new { Name = "George" }, 2, 3),
        new Tuple<object, int, int>(new { Name = "Phil" }, 3, 12),
        new Tuple<object, int, int>(new { Name = "John" }, 4, 3),
        new Tuple<object, int, int>(new { Name = "Giggs" }, 5, 1),
        new Tuple<object, int, int>(new { Name = "Higgins" }, 6, 1)
    };

Ожидаемый результат должен быть сгруппирован Tuples. Иван должен остаться в текущем, потому что нет пользователей с идентификатором пользователя 12. Под ним должны быть Гиггз и Хиггинс, потому что их идентификатор приглашающего равен 1 (идентификатор пользователя для Ивана) и так далее. Результаты:

Ivan (user id = 1)
 Giggs (inviter id = 1)
 Higgins (inviter id = 1)
Phil (user id = 3)
 George (inviter id = 3)
 John (inviter id = 3)

Ответы [ 3 ]

2 голосов
/ 27 июня 2019

Что ж, вы можете сгруппировать по идентификатору приглашающего, затем перебрать исходный список и сопоставить, где идентификатор пользователя совпадает с идентификатором приглашающего, например:

        var list = new List<Tuple<object, int, int>> // item2 - UserId, item3 - InviterId
        {
            new Tuple<object, int, int>(new { Name = "Ivan" }, 1, 12),
            new Tuple<object, int, int>(new { Name = "George" }, 2, 3),
            new Tuple<object, int, int>(new { Name = "Phil" }, 3, 12),
            new Tuple<object, int, int>(new { Name = "John" }, 4, 3),
            new Tuple<object, int, int>(new { Name = "Giggs" }, 5, 1),
            new Tuple<object, int, int>(new { Name = "Higgins" }, 6, 1)
        };

        var groups = list.GroupBy(i => i.Item3);
        var groupedList = new List<string>();

        foreach (var user in list)
        {
            //I'm assuming you actually want to display / store the data as per your results
            var propInfo = user.Item1.GetType().GetProperty("Name");
            groupedList.Add(propInfo.GetValue(user.Item1, null).ToString() + " (user id = " + user.Item2 + ")");
            var group = groups.Where(grp => grp.Key == user.Item2).ToList().SelectMany(g => g);
            foreach (var inviter in group)
            {
                groupedList.Add(propInfo.GetValue(inviter.Item1, null).ToString() + " (inviter id = " + inviter.Item3 + ")");
            }
        }

        // display items in list
        foreach (var item in groupedList)
        {
            Console.WriteLine(item);
        }

Это будет отображать результаты как это:

enter image description here

2 голосов
/ 27 июня 2019

Вот моя попытка. ПРИМЕЧАНИЕ. Этот код предполагает, что в вашем списке указано = UserId.

var list = new List<Tuple<object, int, int>> // item2 - UserId, item3 - InviterId
        {
            new Tuple<object, int, int>(new { Name = "Ivan" }, 1, 12),
            new Tuple<object, int, int>(new { Name = "George" }, 2, 3),
            new Tuple<object, int, int>(new { Name = "Phil" }, 3, 12),
            new Tuple<object, int, int>(new { Name = "John" }, 4, 3),
            new Tuple<object, int, int>(new { Name = "Giggs" }, 5, 1),
            new Tuple<object, int, int>(new { Name = "Higgins" }, 6, 1)
        };

        var grouped = list.ToLookup(t => t.Item2);

        var withInviter = grouped.Select(grp => Tuple.Create(list[grp.Key], grp));

        var sorted = withInviter.OrderBy(t => t.Item1.Item2);

Редактировать: извините, но, как только я прочитал ваш пример снова, я вижуЯ неправильно понял, какие результаты вы ищете.Мне кажется, что пользователей можно разделить на приглашенных и не приглашенных?Я обновлю свой ответ, так как он неправильный.

Редактировать 2: Этот должен работать:

    struct InviterAndInvited {
        public Tuple<object, int, int> Inviter;
        public IEnumerable<Tuple<object, int, int>> Invited;
    }

    public static void Main(string[] args)
    {
        var list = new List<Tuple<object, int, int>> // item2 - UserId, item3 - InviterId
        {
            new Tuple<object, int, int>(new { Name = "Ivan" }, 1, 12),
            new Tuple<object, int, int>(new { Name = "George" }, 2, 3),
            new Tuple<object, int, int>(new { Name = "Phil" }, 3, 12),
            new Tuple<object, int, int>(new { Name = "John" }, 4, 3),
            new Tuple<object, int, int>(new { Name = "Giggs" }, 5, 1),
            new Tuple<object, int, int>(new { Name = "Higgins" }, 6, 1)
        };

        var byInviter = list.ToLookup(u => u.Item3);

        var inviterInveted = list
            .Where(user => byInviter.Contains(user.Item2))
            .Select(user => new InviterAndInvited() {
                Inviter = user,
                Invited = byInviter[user.Item2] 
            } );

        foreach (var grp in inviterInveted) // Print results
        {
            Console.WriteLine(grp.Inviter.Item1);
            foreach (var user in grp.Invited) {
                Console.WriteLine("\t" + user.Item1);
            }
        }
    }

Редактировать 4: Изменен GetOrDefault на []

0 голосов
/ 10 июля 2019

Мое решение в LINQPad:

var list = new List<Tuple<object, int, int>> // item2 - UserId, item3 - InviterId
            {
                new Tuple<object, int, int>(new { Name = "Ivan", Role = "Bidder" }, 1, 12),
                new Tuple<object, int, int>(new { Name = "George", Role = "Guest" }, 2, 3),
                new Tuple<object, int, int>(new { Name = "Phil", Role = "Bidder" }, 3, 12),
                new Tuple<object, int, int>(new { Name = "John", Role = "Guest" }, 4, 3),
                new Tuple<object, int, int>(new { Name = "Giggs", Role = "Guest" }, 5, 1),
                new Tuple<object, int, int>(new { Name = "Higgins", Role = "Guest" }, 6, 1),
                new Tuple<object, int, int>(new { Name = "Alone", Role = "Guest" }, 7, 111),
                new Tuple<object, int, int>(new { Name = "Alone2", Role = "Guest" }, 8, 112),
            };

        var dict = new Dictionary<int, List<object>>();

        foreach (var element in list)
        {
            if (!dict.ContainsKey(element.Item2))
            {
                dict.Add(element.Item2, new List<object> { element.Item1 });
            }
        }

        foreach (var element in list)
        {
            if (dict.ContainsKey(element.Item3))
            {
                dict[element.Item3].Add(element);
            }
        }

        dict.Where(d => d.Value.Count() > 1).ToDictionary(kvp => kvp.Key, kvp => kvp.Value).Dump();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...