【问题标题】:Order by second Dimesion of String Array in C#C#中按字符串数组的第二维排序
【发布时间】:2018-05-10 15:22:55
【问题描述】:

我们有像

这样的二维字符串数组
"0" => {"John","23"},
"1" => {"Doe","12"},
"2" => {"Maria","41"},
 .......

我们想像这样对这个数组进行排序

 "0" => {"Maria","41"},
 "1" => {"John","23"},
 "2" => {"Doe","12"},
     .......

我们的数组代码String[,] kelimedeger = new String[20, 2];

我们希望通过kelimedeger[i,1]订购

【问题讨论】:

  • 你为什么不开始使用类呢?例如:var kelimedeger=new List<User>{new User{Age=41, Name="Maria"}}
  • @TimSchmelter 我猜是multi-dimensional array sorting is popular today。虽然可能是完全不同的背景。
  • @TimSchmelter 我们更喜欢它,您能否解释一下我们如何按年龄对这个列表进行排序?
  • @MahirTahaÖzdin: kelimedeger=kelimedeger.OrderBy(u=>u.Age).ToList()kelimedeger.Sort((u1, u2) => u1.Age.CompareTo(u2.Age));
  • @TimSchmelter 我们有一个 for 循环,可以一一添加所有用户,我们将在其中定义 var kelimedeger,并且我们可以在其中一一添加用户,谢谢

标签: c# arrays sorting multidimensional-array


【解决方案1】:

关于排序

我在这里看到的一个问题是,您的第二个“字符串”实际上不是字符串,而是数字。因此,您实际上有一个有名字和年龄的人。

为什么这很重要?

排序取决于数据的类型。字符串按字母顺序排序,而数字按数字排序。

考虑以下列表:

1, 2, 17, 11, 100, 20, 34

这可以通过多种方式排序

Numerical    Alphabetical
---------    ------------
1            1
2            100
11           11
17           17
20           2
34           20
100          34

鉴于您很可能希望按数字排序,您需要将数据存储为int,而不是string


如何存储数据?

这取决于您的用例。如果保证名称是唯一的,那么您可以使用Dictionary<string,int>。否则,我建议您创建一个类 Person 并使用 ICollection<Person> 来存储它们。

作为Dictionary<string, int>

如果可以保证名称在您的域中是唯一的,则此方法很有用。此外,它只使用内置类型。

namespace DictionaryTest
{
  public class Program
  {
    public static void Main(string[] args)
    {
      //Create a dictionary to store people
      Dictionary<string, int> people = new Dictionary<string, int>();

      //Add some people. Note that this is type-safe
      people.Add("John", 23);
      people.Add("Doe", 12);
      people.Add("Maria", 41);
      //people.Add("John", 55); // <-- This will fail because there is already a John

      //Create queries to ensure correct sorting
      var peopleByName = from p in people
                         orderby p.Key //Our name is the key, the age is the value
                         select new {Name = p.Key, Age = p.Value};

      var peopleByAge = from p in people
                        orderby p.Value
                        select new {Name = p.Key, Age = p.Value};

      var peopleByAgeDescending = from p in people
                                  orderby p.Value descending
                                  select new {Name = p.Key, Age = p.Value};

      //Execute the query and print results
      foreach(var person in peopleByAge)
      {
        Console.WriteLine("Hello, my name is {0} and I am {1} years old", person.Name, person.Age);
      }
    }
  }
}

Try it online!


作为ICollection&lt;Person&gt;

这种方法定义了一个类Person,它只包含一个Name 和一个Age 属性,但可以扩展为包含更多信息、方法等。

namespace ClassTest
{
  public class Program
  {
    public static void Main(string[] args)
    {
      //Create a list to store people
      ICollection<Person> people = new List<Person>();

      //Add some people. Note that this is type-safe
      people.Add(new Person(){ Name = "John", Age = 23, FavouriteColour = "Blue" });
      people.Add(new Person(){ Name = "Doe", Age = 12});
      people.Add(new Person(){ Name = "Maria", Age = 41, FavouriteColour = "Purple" });
      people.Add(new Person(){ Name = "John", Age = 55, FavouriteColour = "Gray" }); //<-- You can indeed have two people with the same name

      //Create queries to ensure correct sorting
      var peopleByName = from p in people
                         orderby p.Name
                         select p;

      var peopleByAge = from p in people
                        orderby p.Age
                        select p;

      var peopleByAgeDescending = from p in people
                                  orderby p.Age descending
                                  select p;


      //Execute the query and print results
      foreach(var person in peopleByAge)
      {
        Console.WriteLine("Hello, my name is {0} and I am {1} years old.", person.Name, person.Age);
        if(person.FavouriteColour != null)
        {
          Console.WriteLine("My favourite colour is {0}.", person.FavouriteColour);
        }
        else
        {
          Console.WriteLine("I have no favourite colour.");
        }
        Console.WriteLine(); //Add a new line for better readability
      }
    }
  }

  public class Person
  {
    public string Name { get; set; }
    public int Age { get; set; }
    public string FavouriteColour { get; set; }
  }
}

Try it online!


我个人更喜欢第二种方法,因为它更具可扩展性,并且不需要名称的唯一性。它允许您随心所欲地扩展Person 类,并为您提供更多排序选项。

【讨论】:

    【解决方案2】:

    要对二维数组进行排序,您需要将每一行转换为一维数组,并将其保存在 List 或类似名称中。然后,您可以按列对列表进行排序。排序后,您需要将列表转换回二维数组。 这是一种可以用于排序的方法:

    public static T[,] Sort2DArray<T>(T[,] array, int column, bool ascending = true)
    {
        int i = 0;
        List<T[]> items = new List<T[]>();
    
        int columns = array.GetLength(1);
        int rows = array.GetLength(0);
    
        T[] obj = new T[columns];
        foreach (var item in array)
        {
            obj[i % columns] = item;
            if ((i + 1) % 2 == 0)
            {
                items.Add(obj);
                obj = new T[columns];
            }
    
            i++;
        }
    
        var ordered = ascending ? items.OrderBy(a => a[column]) : items.OrderByDescending(a => a[column]);
    
    
        T[,] result = new T[rows, columns];
        for (int r = 0; r < rows; r++)
        {
            var row = ordered.ElementAt(r);
            for (int c = 0; c < columns; c++)
            {
                result[r, c] = row[c];
            }
        }
        return result;
    }
    

    您的代码如下所示:

    string[,] array =
    {
        {"John", "23" },
        {"Doe", "12" },
        {"Maria", "41" },
    };
    
    string[,] ordered = Sort2DArray(array, 1);//Sort by column 1 / Age
    

    将二维数组转换为一维数组并返回并不是对值进行排序的最佳例程。最好的方法是创建一个类来存储您的数据,正如 David Stockinger 和 Tim Schmelter 所说。

    【讨论】:

      猜你喜欢
      • 2015-06-27
      • 1970-01-01
      • 2015-10-13
      • 1970-01-01
      • 2021-08-16
      • 2014-08-10
      • 1970-01-01
      • 2011-12-19
      相关资源
      最近更新 更多