【问题标题】:Print array with LINQ使用 LINQ 打印数组
【发布时间】:2016-06-18 11:07:39
【问题描述】:

我得到了以下代码,我试图在没有我在 LINQ 行之后创建的 foreach 的情况下打印 teenAgerStudents。 我可以在 LINQ 行中添加打印吗? 我可以用另一个新的 LINQ 行代替 foreach 打印吗?

class Student
{
    public int StudentID { get; set; }
    public string StudentName { get; set; }
    public int Age { get; set; }
}
class Program
{
    static void Main(string[] args)
    {
        Student[] studentArray = {
                new Student() { StudentID = 1, StudentName = "John", Age = 18 } ,
                new Student() { StudentID = 2, StudentName = "Steve",  Age = 21 } ,
                new Student() { StudentID = 3, StudentName = "Bill",  Age = 25 } ,
                new Student() { StudentID = 4, StudentName = "Ram" , Age = 20 } ,
                new Student() { StudentID = 5, StudentName = "Ron" , Age = 31 } ,
                new Student() { StudentID = 6, StudentName = "Chris",  Age = 17 } ,
                new Student() { StudentID = 7, StudentName = "Rob",Age = 19  } ,
    };
        Student[] teenAgerStudents = studentArray.Where(s => s.Age > 12 && s.Age < 20).ToArray();

        foreach (var item in teenAgerStudents)
        {
            Console.WriteLine(item.StudentName);
        }
};

【问题讨论】:

  • 是的,你可以。对于简单的情况,这很好。但是,LINQ 的性能往往比编写代码差很多。我倾向于尽可能避免它,除非我绝对确定性能不是,也永远不会成为一个因素。

标签: c# linq


【解决方案1】:

这将起作用:

studentArray.Where(s => s.Age > 12 && s.Age < 20)
            .ToList()
            .ForEach(s => Console.WriteLine(item.StudentName));

Array.ForEach 接受Action&lt;T&gt;,因此它没有返回值。如果你以后需要这个数组,你应该坚持你的旧代码。

当然你也可以在第二个语句中使用ForEach:

List<Student> teenAgerStudent = studentArray.Where(s => s.Age > 12 && s.Age < 20).ToList();
teenAgerStudent.ForEach(s => Console.WriteLine(s.StudentName));

但这会降低它的可读性(在我看来),所以在这种情况下我会坚持使用旧的 foreach 循环。

【讨论】:

  • 在第一种情况下,只需删除 ToArray() - 它不会添加任何内容。
  • @Zastai 那行不通,ForEach 没有为IEnumerable 定义
  • 我的错。当我通过手机发表评论并且无法快速查看文档时,就会发生这种情况。
  • 第二个代码正是我要找的,但它不起作用,ForEach 下有一条红线(错误)
  • @AlexanderDerck 评论不是给你的:) 你的答案很好(如果你用s 替换item :)
【解决方案2】:

我不喜欢使用 LINQ(一种函数式编程系统)来产生副作用。我宁愿将输出 foreach 更改为:

Console.WriteLine(string.Join(Environment.NewLine, 
    teenAgerStudents.Select(s => s.StudentName));

【讨论】:

    【解决方案3】:

    试试这个:

      // There's no need in materialization, i.e. "ToArray()"
      var target = studentArray 
        .Where(student => student.Age > 12 && student.Age < 20) // teen
        .Select(student => String.Format("Id: {0} Name: {1} Age {2}", 
                  student.Id, student.Name, student.Age));
    
      // Printing out in one line (thanks to String.Join)
      Console.Write(String.Join(Environment.NewLine, target));
    

    【讨论】:

    • 这是一种非常独特的方法。强调target 尚未执行并将在真正需要时执行的事实。 +1。
    • 但是收集完整的结果集,浪费内存。流式传输结果更具可扩展性。
    • @Zastai:这取决于数据的大小。由于数据表示为 array (因此整个数据都在内存中)我假设我们有足够的内存用于String.Join (如果我们从 file,流媒体将是一个重点)
    • 问题中的示例代码通常只是一个示例;我尽量不要过分依赖它。但是,是的,有了这个数组就可以了。
    【解决方案4】:

    此行会将您的 teenAgerStudents 姓名打印到控制台,每行一个。

    Console.Write(string.Join(Environment.NewLine, studentArray.Where(s => s.Age > 12 && s.Age < 20).Select(s=>s.StudentName)));
    

    它替换了teenAgerStudents 初始化和foreach。

    如果您仍然需要初始化您的 teenAgeStudents 列表,您可以将前一行分成两部分

    //get the teenager students in form of IEnumerable<Student>.
    //cast it to array with .ToArray() after .Where() if needed.
    var teenAgerStudents = studentArray.Where(s => s.Age > 12 && s.Age < 20);
    //print only the students' names
    Console.Write(string.Join(Environment.NewLine,teenAgerStudents.Select(s=>s.StudentName)));
    

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2023-03-10
      • 2022-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-20
      • 2016-02-11
      相关资源
      最近更新 更多