【问题标题】:How to rename data using Linq based on the location of elements?如何根据元素的位置使用 Linq 重命名数据?
【发布时间】:2011-02-04 08:04:12
【问题描述】:

如果我有一个Effect 集合,即IEnumerable<Effect>,,如何根据它们在集合中的位置设置它们的 .Name 属性?

所以最后,我只是希望它们从 1 开始重命名为 n。

<inside the collection>
effectInstance1.Name = Effect 1;
effectInstance2.Name = Effect 2;
effectInstance3.Name = Effect 3;
...

Linq 可以做到这一点吗?

【问题讨论】:

    标签: c# .net linq ienumerable


    【解决方案1】:

    LINQ 并不是真正用于突变无论如何;但是,您可以使用包含索引的 Select 重载。但说实话?只需循环并保留一个计数器。更容易理解,这很重要

    int position = 0;
    foreach(var obj in collection) {
        position++;
        obj.Name = "Effect " + position.ToString();
    }
    

    【讨论】:

    • 您真的想在循环中使用字符串连接吗?你可能比我更清楚;你什么时候使用 String.Format 和 StringBuilder 在简单的连接上“收支平衡”?
    • @KeithS:你会用 StringBuilder 做什么?
    • @KeithS 使用 StringBuilder 如果您对单个 string 变量(如 string s = ""; foreach (...) s += x;)进行 concat,则很有意义。这里每次迭代只连接两个字符串。 StringBuiler 的开销会更大。
    • 问题是关于用 LINQ 解决,为什么我们应该提出其他解决方案?
    • @KeithS :我必须回应安德烈所说的一切; StringBuilder 每次迭代在这里会很傻,与每个项目对Concat 的单个调用相比。
    【解决方案2】:
    var n = 0;
    collection.ForEach(x=>x.Name = "Effect {0}".FormatWith(++n));
    

    这些是我在 3.5 中使用的简单扩展方法:

    public static void ForEach<T>(this IEnumerable<T> collection, Action<T> lambda)
    {
        foreach(var element in collection)
            lambda(element);
    }
    
    public static string FormatWith(this string base, params object[] args)
    {
        return String.Format(base, args);
    }
    

    【讨论】:

    • 我有点希望这是格式化字符串的默认方法(类似于 Python 的 string.format),但我看不到将 foreach 语句隐藏在 ForEach 中的价值(有副作用!)扩展方法。但是它闻起来很像Ruby,所以我想肯定有人喜欢这种风格。
    • 这确实是一种风格偏好,我从未说过它没有副作用。我发现当重复操作很简单时,将其粘贴在 Linq 链或集合的末尾会更容易。最好的情况,这是我可以将其表示为委托引用的方法:collection.ForEach(collection2.Add);
    【解决方案3】:

    这不是用 LINQ 解决的最好办法,但可能的:

    class Program
    {
        private class Effect
        {
            public string Name { get; set; }
        }
    
        static void Main(string[] args)
        {
            List<Effect> list = new List<Effect> {new Effect(), new Effect(), new Effect()};
    
            var newElements = list.Select((element, index) =>
            {
                element.Name = "Effect " + index.ToString();
                return element;
            });
    
    
            foreach (var effect in newElements)
            {
                Console.WriteLine(effect.Name);
            }
        }
    }
    

    输出:

    效果 0

    效果1

    效果2

    【讨论】:

    • 那为什么不使用ForEach呢?为什么创建 new 列表只是为了修改前一个。这绝对是滥用 linq
    • 你想如何将 foreach 与 linq 一起使用?
    • @Restuta 如果问题不能用 Linq 完美有效地解决,那意味着你不应该使用 Linq。
    • 这并不意味着您不应该回答“如何使用 linq 解决此问题”的源问题 没有人询问您对其他解决方案的看法。总的来说,我同意。
    • List.ForEach 不是 linq 方法,顺便说一句。
    猜你喜欢
    • 2012-02-26
    • 2021-10-20
    • 2013-09-06
    • 2022-09-28
    • 1970-01-01
    • 2019-09-02
    • 2016-12-16
    • 2021-11-01
    • 1970-01-01
    相关资源
    最近更新 更多