C# отсортировать список по индексу другого списка

316
15 января 2018, 06:28

Имеется List<string> с получаемыми данными из VK. В нем хранятся Id пользователей.

Эти данные перебираются и делается множественный запрос (execute) на получение имени пользователей и групп. В response хранится json из двух массивов: первый - результат запроса users.get, второй - результат запроса groups.getById. Эти данные записываются в другой JSON, в котором после этого должны возвращаться функцией и использоваться в другом участке кода.

Проблема: при записи элементов в JArray, они сортируются не в порядке диалогов, а сперва значения запроса users.get, а затем groups.getById, тем самым индексы (и расположение) элементов JArray расположены в таком порядке: 0 1 2 3 4 5 6 7 8 10 11 12 13 14 15 16 17 18 19 9

Где, "9" - это данные группы. Группы в список добавляются в самый конец, и все значения в списке "смещаются". Как можно поместить 9 на свое место?

UPDATE: Предварительно, все идентификаторы во время разбора response метода messages.getDialogs помещаются в переменные groupIds и userIds соответственно. А так же абсолютно все идентификаторы (и групп, и пользователей) помещаются в List idList; (В этом участке кода этого не показано.) Привожу пример кода:

             //Подготовка множественного запроса к VK API.
         //userids - string - с id пользователей через запятую. Записываются при разборе response messages.getDialogs. 
        string method = "API.users.get({\"user_ids\":\"" + userIds + "\", \"fields\":\"photo_50\"})";
         //groupIds - string - с id групп через запятую. Записываются так же при разборе response messages.getDialogs.
         //Если строка не пустая, то к множественному запросу присоеденить запрос по получению данных группы
        if (groupIds.Length > 0)
            method += ", API.groups.getById({\"group_ids\":\"" + groupIds + "\"})";
        // Множественный запрос (execute)
        var request = JObject.Parse(await BatchRequest(method));
        string uid = "";
        string name = "";
        string avatar = "";
        // JArray, в который помещаю id, name, avatar пользователей и групп вместе.
        JArray preparedJson = new JArray();
        foreach (var data in request["response"])
        {
            if (data is JArray)
            {
                foreach (var arr in data)
                {
                    if (arr["uid"] == null && arr["gid"] != null)
                    {
                        uid = arr["gid"].ToString();
                        name = arr["name"].ToString();
                        avatar = arr["photo"].ToString();
                    } else
                    {
                        uid = arr["uid"].ToString();
                        name = arr["first_name"].ToString() + " " + arr["last_name"].ToString();
                        avatar = arr["photo_50"].ToString();
                    }
                    user.uid = uid;
                    user.name = name;
                    user.avatar = avatar;
                    // Собственно, само помещение объекта User (с полями uid,name,avatar) в JArray.
                    preparedJson.Add(JsonConvert.SerializeObject(user));
                }
            }
        }

        // Перебор Json так, как это перебиралось бы в другом методе, вызывающий этот
        foreach (var data in preparedJson)
        {
            var json = JObject.Parse(data.ToString());
            // Собственно, выведет список из значений json, записанных ранее. В порядке, в котором описаны в вопросе
            System.Diagnostics.Debug.WriteLine(data);
            // Выводит индексы всех идентификаторов. Вывод получается смешанным - сперва идут пользователи, и в самом конце группа. Вывод указан в вопросе.
            System.Diagnostics.Debug.WriteLine(idList.IndexOf(json["uid"].ToString()));
        }

UPDATE: Привожу значения списков: idList:

        26094570
        32375480
        46086417
        2505581
        24862495
        6123568
        701580
        25081541
        16111376
        30242512
        31238032
        5927769
        -15736980
        27044567
        42927784
        1028357
        15203959
        3042183
        29652691
        27378364

Это идентификаторы пользователей в списке диалогов. По сути это и есть список диалогов, только с ID пользователей и групп (без их сообщений и т.д.).

А это значения из JArray preparedJson:

        { "uid":"26094570","name":"username","avatar":"avatar"}
        { "uid":"32375480","name":"username","avatar":"avatar"}
        { "uid":"46086417","name":"username","avatar":"avatar"}
        { "uid":"2505581","name":"username","avatar":"avatar"}
        { "uid":"24862495","name":"username","avatar":"avatar"}
        { "uid":"6123568","name":"username","avatar":"avatar"}
        { "uid":"701580","name":"username","avatar":"avatar"}
        { "uid":"25081541","name":"username","avatar":"avatar"}
        { "uid":"16111376","name":"username","avatar":"avatar"}
        { "uid":"30242512","name":"username","avatar":"avatar"}
        { "uid":"31238032","name":"username","avatar":"avatar"}
        { "uid":"5927769","name":"username","avatar":"avatar"}
        { "uid":"27044567","name":"username","avatar":"avatar"}
        { "uid":"42927784","name":"username","avatar":"avatar"}
        { "uid":"1028357","name":"username","avatar":"avatar"}
        { "uid":"15203959","name":"username","avatar":"avatar"}
        { "uid":"3042183","name":"username","avatar":"avatar"}
        { "uid":"29652691","name":"username","avatar":""}
        { "uid":"27378364","name":"username","avatar":"avatar"}
        { "uid":"-15736980","name":"groupname","avatar":"avatar"}

Обратите внимание на порядок идентификаторов. В моих диалогах id группы идет после id 5927769, а здесь в самом конце списка. Весь мой вопрос состоит в том, КАК последний id списка (группу) переместить на свое место, после id 5927769?

Answer 1

Я бы сделал так. Во-первых, положил бы данные в словарь: вместо JArray preparedJson = new JArray(); написал бы var usersById = new Dictionary<string, User>();, а вместо

user.uid = uid;
user.name = name;
user.avatar = avatar;
// Собственно, само помещение объекта User (с полями uid,name,avatar) в JArray.
preparedJson.Add(JsonConvert.SerializeObject(user));

соответственно

var user = new User() { uid = uid, name = name, avatar = avatar };
usersById[uid] = user;

А после окончания цикла собрал бы данные:

JArray preparedJson = new JArray();
foreach (var id in idList)
    preparedJson.Add(JsonConvert.SerializeObject(usersById[id]));

Ну или с проверкой:

foreach (var id in idList)
    if (usersById.TryGetValue(id, out var user))
        preparedJson.Add(JsonConvert.SerializeObject(user));

Ещё один вариант с LINQ. После цикла foreach (var data in request["response"]) { ... } добавьте:

preparedJson = new JArray(
    from id in ids join user in preparedJson on id equals user["uid"] select user);

(надеюсь, что порядок в join'е определён однозначно). Это и есть та самая сортировка по элементу в другом массиве.

Answer 2

Фильтрацию можно выполнить следующим образом пройтись по всем значениям пользователей и найти и добавить все совпадения в новую коллекцию. Также работать с JArray неудобно потому я выполнил десериализацию в модель. Пример:

class Program
{
    public class RequestModel
    {
        [JsonProperty("data")]
        public List<RequestRow> Data { get; set; }
    }
    public class RequestRow
    {
        [JsonProperty("uid")]
        public string Uid { get; set; }
        [JsonProperty("name")]
        public string Name { get; set; }
        [JsonProperty("avatar")]
        public string Avatar { get; set; }
    }
    static void Main(string[] args)
    {
        //Десериализуем данные для удобства работы
        var request = JsonConvert.DeserializeObject<RequestModel>(GetJsonString());
        //Получаем список пользователей
        var userIds = GetUsersIds();
        //Создаем коллекцию в которую добавим только те элементы и в таком порядке как указанно в списке
        var newList = new List<RequestRow>();
        //Непосредственная фильтрация
        foreach (var userId in userIds)
        {
            var row = request.Data.FirstOrDefault(x => x.Uid == userId);
            if (row != null)
            {
                newList.Add(row);
            }
        }
        //Ну и выведем для наглядности
        foreach (var requestRow in newList)
        {
            Console.WriteLine(requestRow.Uid);
        }
        Console.ReadKey();
    }
    /// <summary>
    /// Получение списка ID
    /// </summary>
    public static List<string> GetUsersIds()
    {
        return new List<string>()
            {
                "26094570",
                "32375480",
                "46086417",
                "2505581",
                "24862495",
                "6123568",
                "701580",
                "25081541",
                "16111376",
                "30242512",
                "31238032",
                "5927769",
                "-15736980",
                "27044567",
                "42927784",
                "1028357",
                "15203959",
                "3042183",
                "29652691",
                "27378364"
            };
    }
    /// <summary>
    /// Получение исходной строки JSON
    /// </summary>
    public static string GetJsonString()
    {
        var result =
            @"
                {
                  ""data"": [
                    {
                      ""uid"": ""26094570"",
                      ""name"": ""username"",
                      ""avatar"": ""avatar""
                    },
                    {
                      ""uid"": ""32375480"",
                      ""name"": ""username"",
                      ""avatar"": ""avatar""
                    },
                    {
                      ""uid"": ""46086417"",
                      ""name"": ""username"",
                      ""avatar"": ""avatar""
                    },
                    {
                      ""uid"": ""2505581"",
                      ""name"": ""username"",
                      ""avatar"": ""avatar""
                    },
                    {
                      ""uid"": ""24862495"",
                      ""name"": ""username"",
                      ""avatar"": ""avatar""
                    },
                    {
                      ""uid"": ""6123568"",
                      ""name"": ""username"",
                      ""avatar"": ""avatar""
                    },
                    {
                      ""uid"": ""701580"",
                      ""name"": ""username"",
                      ""avatar"": ""avatar""
                    },
                    {
                      ""uid"": ""25081541"",
                      ""name"": ""username"",
                      ""avatar"": ""avatar""
                    },
                    {
                      ""uid"": ""16111376"",
                      ""name"": ""username"",
                      ""avatar"": ""avatar""
                    },
                    {
                      ""uid"": ""30242512"",
                      ""name"": ""username"",
                      ""avatar"": ""avatar""
                    },
                    {
                      ""uid"": ""31238032"",
                      ""name"": ""username"",
                      ""avatar"": ""avatar""
                    },
                    {
                      ""uid"": ""5927769"",
                      ""name"": ""username"",
                      ""avatar"": ""avatar""
                    },
                    {
                      ""uid"": ""27044567"",
                      ""name"": ""username"",
                      ""avatar"": ""avatar""
                    },
                    {
                      ""uid"": ""42927784"",
                      ""name"": ""username"",
                      ""avatar"": ""avatar""
                    },
                    {
                      ""uid"": ""1028357"",
                      ""name"": ""username"",
                      ""avatar"": ""avatar""
                    },
                    {
                      ""uid"": ""15203959"",
                      ""name"": ""username"",
                      ""avatar"": ""avatar""
                    },
                    {
                      ""uid"": ""3042183"",
                      ""name"": ""username"",
                      ""avatar"": ""avatar""
                    },
                    {
                      ""uid"": ""29652691"",
                      ""name"": ""username"",
                      ""avatar"": """"
                    },
                    {
                      ""uid"": ""27378364"",
                      ""name"": ""username"",
                      ""avatar"": ""avatar""
                    },
                    {
                      ""uid"": ""-15736980"",
                      ""name"": ""groupname"",
                      ""avatar"": ""avatar""
                    }
                  ]
                }";
        return result;
    }
}

Результат выполнения:

26094570
32375480
46086417
2505581
24862495
6123568
701580
25081541
16111376
30242512
31238032
5927769
-15736980
27044567
42927784
1028357
15203959
3042183
29652691
27378364
READ ALSO
Нужно при нажатии на боковые кнопки мыши производились функции копи паст, вместо &ldquo;назад&rdquo; и &ldquo;вперед&rdquo; соответственно. Глобально!

Нужно при нажатии на боковые кнопки мыши производились функции копи паст, вместо “назад” и “вперед” соответственно. Глобально!

Реализован глобальный хук и назначение функций на клавиши, нужно отменять действие "назад" и "вперед"

224
MS SQL SERVER связь многие ко многим

MS SQL SERVER связь многие ко многим

Вопрос следующийЕсть 2 таблицы: МАРШРУТ: Достопримечательность:

220
Привет мир на C#

Привет мир на C#

ЗдравствуйтеМне необходимо объединить в функции текст и переменную

190