Как обновить список <(T, T, T)> в C # - PullRequest
1 голос
/ 19 сентября 2019

У меня есть следующий список, и я хотел бы обновить его.

List<(ulong channel, ulong user, object answer)> questions = 
    Globals.Discord.Interactive.Questions;

Я попытался использовать LINQ, но не смог заставить его работать.

questions.Find(x => x.channel == channel.Id).answer = null;

Индексыне представляется возможным использовать.

questions[questions.FindIndex(x => x.channel == channel.Id)].answer = null;

Как я могу это сделать?

Ответы [ 2 ]

1 голос
/ 19 сентября 2019

Вы можете использовать функциональное преобразование в коллекциях с неизменяемыми типами, например, используя сопоставление с образцом:


var data = new List<(ulong channel, ulong user, object answer)>() {
  (1, 2, "a1"), 
  (4, 5, "a2") 
};

data.Select(x =>
{
    switch (x)
    {
        case var z when z.channel == 1: return (z.channel, z.user, null);
        default: return x;
    }
});

Обратите внимание, что вы не изменяете существующую коллекцию, а создаете IEnumerable, которыйпревратит это.Вы можете материализовать это, например, позвонив .ToList().AsReadOnly().

Если вы предпочитаете более императивный способ, вы можете просто перебрать коллекцию и изменить ее.

var data = new (ulong channel, ulong user, object answer)[] {
    (1, 2, "a1"),
    (4, 5, "a2")
};
for (int i = 0; i < data.Length; i++)
    if (data[i].channel == 1)
        data[i].answer = null;

Одна интересная вещь вВ этом примере вам не нужно создавать новый кортеж и заменять его в массиве: когда вы обращаетесь к структуре в массиве по индексу, он не клонируется, поэтому вы можете изменить его.Это относится только к массиву и не будет работать с List.

1 голос
/ 19 сентября 2019

Что вы можете сделать, это сначала найти Index для обновления, используйте это Index для вывода кортежа, а затем снова используйте Index для предоставления списку с обновленным кортежем.

Что-то вроде:

static void Main(string[] args)
{
    var questions = new List<(ulong channel, ulong user, object answer)>
    {
        (1, 1, 1),
        (2, 2, 2),
        (3, 3, 3),
        (4, 4, 4)
    };

    foreach (var (channel, user, answer) in questions)
    {
        Console.WriteLine(answer);
    }

    var channel3Index = questions.FindIndex((obj) => obj.channel == 3);
    if (channel3Index > -1)
    {
        var question = questions[channel3Index];
        question.answer = 666;
        questions[channel3Index] = question;
    }

    foreach (var (channel, user, answer) in questions)
    {
        Console.WriteLine(answer);
    }

    Console.ReadKey();
}

Причина, по которой вы должны сначала обновить его, а затем заменить его существующим, заключается в том, что вы используете ValueTuples, которые являются типами значений.См .: https://docs.microsoft.com/en-us/dotnet/api/system.valuetuple?redirectedfrom=MSDN&view=netframework-4.8

Редактировать : Если вы не хотите использовать тип значения в своем списке, используйте ссылочный тип.Простой класс подойдет.

  class Program
    {
        public class Question
        {
            public ulong Channel { get; set; }

            public ulong User { get; set; }

            public Object Answer { get; set; }
        }

        static void Main(string[] args)
        {
            var questions = new List<Question>
            {
                new Question
                {
                    Channel = 1,
                    User = 1,
                    Answer = 1
                },
                new Question
                {
                    Channel = 2,
                    User = 2,
                    Answer = 2
                },
                new Question
                {
                    Channel = 3,
                    User = 3,
                    Answer = 3
                },
            };

            foreach (var question in questions)
            {
                Console.WriteLine(question.Answer);
            }

            var channel3Index = questions.FindIndex((obj) => obj.Channel == 3);
            if (channel3Index > -1)
            {
                questions[channel3Index].Answer = 666;
            }

            foreach (var question in questions)
            {
                Console.WriteLine(question.Answer);
            }

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