【问题标题】:How to update a List<(T, T, T)> in C#如何在 C# 中更新 List<(T, T, T)>
【发布时间】:2019-09-19 02:28:02
【问题描述】:

我有以下列表并想更新它。

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;

我该怎么做?

【问题讨论】:

    标签: c# list tuples


    【解决方案1】:

    您可以做的是首先找到要更新的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

    编辑: 如果您不想在 List 中使用值类型,请使用引用类型。一个简单的类就可以了。

      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();
            }
        }
    

    【讨论】:

    • 非常感谢您的回答。你认为这里有比 ValueTuples 列表更好/更容易使用的东西吗?
    • @Laiteux ,请注意FindIndex 只会转换第一个答案。我想,从您的域中,您可能会在同一频道上从不同用户那里获得许多答案。
    • @Fenixil 我的代码正在处理这种可能性,不用担心;)谢谢!
    【解决方案2】:

    您可以对具有不可变类型的集合使用类似函数的转换,例如使用模式匹配:

    
    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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多