【问题标题】:Sorting a list of names with first/last name and age C#使用名字/姓氏和年龄对名称列表进行排序C#
【发布时间】:2016-11-15 00:29:28
【问题描述】:

我想首先按年龄对列表中的姓名进行排序(到目前为止我已经这样做了),但我想知道如何在打印到新文件之前再次按姓氏对这些姓名进行排序。例如,如果我有 5 个 20 岁的不同姓氏的人,我如何确保这 5 个人按字母升序排列?

class Person : IComparable
{
    string vorname;
    string nachname;
    int age;

    public Person(string vorname, string nachname, int age)
    {
        this.age = age;
        this.nachname = nachname;
        this.vorname = vorname;
    }

    public int CompareTo(object obj)
    {
        Person other = (Person)obj;
        int a = this.age - other.age;

        if (a != 0)
        {
            return -a;
        }
        else
        {
            return age.CompareTo(other.age);
        }
    }

    public override string ToString()
    {
        return vorname + " " + nachname + "\t" + age;
    }        
}

class Program
{
    static void Main(string[] args)
    {
        Person[] peeps = new Person[20];

        try
        {
            StreamReader sr = new StreamReader("inputNames.txt");

            int count = 0;

            while (!sr.EndOfStream)
            {
                string data = sr.ReadLine();
                Console.WriteLine();
                string[] info = data.Split(',');
                peeps[count] = new Person(info[0], info[1], int.Parse(info[2]));

                count++;
            }
            Array.Sort(peeps);
            sr.Close();
        }
        catch(FileNotFoundException e)
        {
            Console.WriteLine(e.Message);
        }

        StreamWriter sw = new StreamWriter("outputNames.txt");

        Console.WriteLine();
        foreach (Person p in peeps)
        {
            Console.WriteLine(p);
            sw.WriteLine(p);
        }
        sw.Close();
    }
}

【问题讨论】:

  • EDIT* 没有 linq,我必须使用 IComparable。

标签: c# sorting icomparable


【解决方案1】:

Linq 是你的朋友。您可以在 1 行中重写所有代码:

peeps.OrderBy(x => x.Age).ThenBy(x => x.LastName);

这就是它的全部内容:)。您可以摆脱所有 IComparable 垃圾,那是老派。

编辑:对于 IComparable,您可以这样做:

    public int CompareTo(object obj)
    {
        Person other = (Person)obj;

        if (age < other.age)
            return -1;

        if (String.Compare(vorname, other.vorname) < 0)
            return -1;

        return 1;
    }

似乎适用于我的快速测试,但测试更多:)。

【讨论】:

  • 我忘了提到我正在为学校做这个,它说我必须使用 IComparable。对不起
  • 它适用于名称,但现在年龄数字乱序了。 ://
  • 它现在适用于姓名和年龄,我对其进行了一些更改,它完成了它应该做的事情。非常感谢您的帮助:)
【解决方案2】:

你可以使用 Linq:

 people.OrderBy(person => person.age)
     .ThenBy(person => person.LastName);

【讨论】:

    【解决方案3】:

    有点过时,但仍然。您可以使用Comparers 并在以后根据需要使用它们以获得灵活性:

        public class AgeComparer: Comparer<Person> 
        {
            public override int Compare(Person x, Person y)
            {   
    
               return x.Age.CompareTo(y.Age);      
            }    
        }
        public class LastNameThenAgeComparer: Comparer<Person> 
        {
            public override int Compare(Person x, Person y)
            {       
                if (x.LastName.CompareTo(y.LastName) != 0)
                {
                   return x.LastName.CompareTo(y.LastName);
                }
                else (x.Age.CompareTo(y.Age) != 0)
                {
                   return x.Age.CompareTo(y.Age);
                }    
            }    
        }
    //// other types of comparers
    

    用法:

    personList.Sort(new LastNameThenAgeComparer());
    

    【讨论】:

      【解决方案4】:

      LINQ + 扩展方法

      class Program
      {
          static void Main(string[] args)
          {
              try
              {
                  "inputNames.txt".ReadFileAsLines()
                                  .Select(l => l.Split(','))
                                  .Select(l => new Person
                                  {
                                      vorname = l[0],
                                      nachname = l[1],
                                      age = int.Parse(l[2]),
                                  })
                                  .OrderBy(p => p.age).ThenBy(p => p.nachname)
                                  .WriteAsLinesTo("outputNames.txt");
              }
              catch (Exception e)
              {
                  Console.Error.WriteLine(e.Message);
              }
          }
      }
      public class Person
      {
          public string vorname { get; set; }
          public string nachname { get; set; }
          public int age { get; set; }
      
          public override string ToString()
          {
              return string.Format("{0} {1}\t{2}", this.vorname, this.nachname, this.age);
          }
      }
      public static class ToolsEx
      {
          public static IEnumerable<string> ReadFileAsLines(this string filename)
          {
              using (var reader = new StreamReader(filename))
                  while (!reader.EndOfStream)
                      yield return reader.ReadLine();
          }
          public static void WriteAsLinesTo(this IEnumerable lines, string filename)
          {
              using (var writer = new StreamWriter(filename))
                  foreach (var line in lines)
                      writer.WriteLine(line);
          }
      }
      

      【讨论】:

        【解决方案5】:

        这就是我将如何使用一些 cmets 来实现这样的 person 类。

        //sort a person object by age first, then by last name
            class Person : IComparable<Person>, IComparable
            {
                public string LastName { get; }
                public string FirstName { get; }
                public int Age { get; }
        
                public Person(string vorname, string nachname, int age)
                {
                    LastName = vorname;
                    FirstName = nachname;
                    Age = age;
                }
        
                // used by the default comparer
                public int CompareTo(Person p)
                {
                    // make sure comparable being consistent with equality; this will use IEquatable<Person> if implemented on Person hence better than static Equals from object
                    if (EqualityComparer<Person>.Default.Equals(this, p)) return 0;
        
                    if (p == null)
                        throw new ArgumentNullException(nameof(p), "Cannot compare person with null");
        
                    if (Age.CompareTo(p.Age) == 0)
                    {
                        return LastName.CompareTo(p.LastName);
                    }
                    return Age.CompareTo(p.Age);
                }
        
                // explicit implementation for backward compatiability 
                int IComparable.CompareTo(object obj)
                {
                    Person p = obj as Person;
                    return CompareTo(p);
                }
        
                public override string ToString() => $"{LastName} {FirstName} \t {Age}";
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-01-27
          • 2022-01-14
          • 2010-10-26
          • 2020-11-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多