如何对包含双精度和字符串数据的 Class 列表进行排序

How to Sort a Class List that contain both of double and string data

人class:

class Person
    {
        public string ID;
        public string Name;
        public string PClass;
        public string Age;
        public string Sex;
        public string Survived;
        public string SexCode;
        public Person(string id,string name,string pclass,string age,string sex,
            string survived,string sexcode)
        {
            ID = id;
            Name = name;
            PClass = pclass;
            Age = age;
            Sex = sex;
            Survived = survived;
            SexCode = sexcode;
        }

我的程序代码:

class Program
    {
        static void Main(string[] args)
        {


            string[] data = File.ReadAllLines("titanic.csv");
            data = data.Skip(1).ToArray();
            List<Person> personList = new List<Person>();
            List<Person> personList_name = new List<Person>();
            List<Person> personList_pclass = new List<Person>();
            List<Person> personList_age = new List<Person>();
            List<Person> personList_sex = new List<Person>();
            List<Person> personList_id = new List<Person>();

            for (int i = 0; i < data.Length; i++)
            {
                string[] temp = Regex.Split(data[i], ",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)");
                Person person = new Person(temp[0], temp[1], temp[2],temp[3],
                temp[4], temp[5], temp[6]);
                personList.Add(person);

            }

            personList_name = personList.OrderBy(x => x.Name).ToList();
            personList_pclass = personList.OrderBy(z => z.PClass).ToList();
            personList_sex = personList.OrderBy(w => w.Sex).ToList();
            int id_;
            int age_;
            personList_age = personList.OrderBy(y => int.TryParse(y.Age, out age_)).ToList();
            //personList_id = personList.OrderByDescending(int.TryParse(ID, out number)).ToList();
            personList_id = personList.OrderBy(o => int.TryParse(o.ID, out id_)).ToList();

            while (true)
            {
                Console.WriteLine(" Please select your filtring method:\n" +
                    "1-By Name\n2-By Pclass\n3-By Age\n4-By Sex\n5-By ID\n Press -1 to quit.");
                string selection = Console.ReadLine();
                if (selection == "-1")
                {
                    break;
                }

                        Console.WriteLine(("{0,-10}{1,70}{2,20}{3,20}{4,20}{5,20}{6,20}"), item.ID.Trim('"'), item.Name.Trim('"'), item.PClass.Trim('"')
                            , item.Age, item.Sex.Trim('"'), item.Survived.Trim('"')
                            , item.SexCode.Trim('"'));
                    }
                 }
                if (selection == "3")
                {
                    Console.WriteLine(("{0,-10}{1,70}{2,20}{3,20}{4,20}{5,20}{6,20}"), "ID", "NAME", "PCLASS", "AGE", "SEX", "SURVIVED", "SEXCODE");
                    foreach (var item in personList_age)
                    {
                        Console.WriteLine(("{0,-10}{1,70}{2,20}{3,20}{4,20}{5,20}{6,20}"), item.ID.Trim('"'), item.Name.Trim('"'), item.PClass.Trim('"')
                            , item.Age, item.Sex.Trim('"'), item.Survived.Trim('"')
                            , item.SexCode.Trim('"'));

                    }
                }

            }
        }
    }

我可以对 CSV 文件中的字符串数据进行排序,例如姓名,但是对于年龄和 ID,我无法获得正确的顺序(升序或降序) 我已经搜索了很多关于这个问题的信息。尝试使用 Icomparable 和 Tryparse 但没有任何积极的结果。问题是 Orderby 将年龄和 ID 作为字符串处理。但是,如果我将 Age 和 ID 定义为 double 或 int,我将在定义临时数组时得到 "cannot convert"。请提供任何有用的建议或解决方案?

这就是我根据年龄订购时发生的情况。看来还是按ID点餐!
(来源:up-00.com

提供函数而不是表达式:

personList_age = personList.OrderBy
(
    y => {
             int age;
             bool ok = int.TryParse(y.Age, out age);
             return ok ? age : default(int);
         }
).ToList();

或者为了保持整洁可以写一个扩展方法:

static void int ToInt(this string input)
{
    int n;
    bool ok = int.TryParse(input, out n);
    return ok ? n : default(int);
}

然后这样调用:

personList_age = personList.OrderBy( y => t.Age.ToInt());

你试过了吗

personList.OrderBy(x => Convert.ToInt32(x.id)).ToList();

?

这样它应该按整数值对它们进行排序

问题是 TryParse returns 一个 bool 而不是解析值。 OrderBy 然后命令 true vs false。在升序中,false 之前 true.

如果您希望这些值始终是整数,您有几种选择。

更好的(在我看来)是将 class 中的那些属性更改为整数并在构造函数中进行解析,如果传递了错误的值则抛出异常(不允许错误的 Person待创建)。

第二个选项是在 OrderBy 内切换到 int.Parse。这只有在所有值都可以被解析时才有效,否则会抛出异常。

如果你必须使用TryParse(例如它不能保证是整数数据并且你不能改变你的class定义),你可以使用多语句lambda:

personList.OrderBy(person => { 
     int value; 
     return int.TryParse(person.ID, out value) ? value : -1;
});

您可能希望根据您希望它们排序的位置为失败案例选择不同的值。在上面的例子中,所有的失败都会首先出现——尽管 假设 没有 ID 可能是负数。您可以改用 int.MinValue。如果你想让它们最后出现,你可以使用 int.MaxValue——尽管如果你的 IDs 可以合法地那么大,你就会遇到问题(我认为至少可以安全地假设没有人会有一个 age 那么大)。

另一种选择是通过首先使用 Select 创建一个包含您需要的数据的匿名类型来过滤掉失败(成功解析,如果适用,值和您的原始 Person)。然后使用 Where 过滤我们无法解析的任何值,然后对解析的数据使用 OrderBy。最后使用另一个 Select 从匿名类型中提取你的 Person

personList.Select(p => {
     int value; 
     var ok = int.TryParse(p.ID, out value);
     return new { Ok = ok, ID = value, Person = p };
})
.Where(result => result.Ok)
.OrderBy(result => result.ID)
.Select(result => result.Person);