关于排序:从文本文件中读取和在C#中排序的最佳方式

Best way to read from text file and sort in C#

如何获取一个一周中从文本中读取的未排序日期的字符串数组,并将其转换为可以在排序算法中使用的内容?

我猜我每天都要分配一个带有if语句的数字,但是我的生活中根本无法理解它。

这是我已经做的。SH1文件正在按我希望的方式运行。文本文件只是一个很长的数字列表,所以我可以很容易地将它们转换为双精度。

至于那些日子(还有日期,但我还没到那一天,所以忽略那些已经存在的,因为它不起作用)我不知道该怎么做。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
class Algorithm
{

    // Sorting Algorithms
    public static void Quick_Sort(double[] data, int left, int right)
    {
        double temp;
        int i, j;
        double pivot;
        i = left;
        j = right;
        pivot = data[(left + right) / 2];
        do
        {
            while ((data[i] < pivot) && (i < right)) i++;
            while ((pivot < data[j]) && (j > left)) j--;
            if (i <= j)
            {
                temp = data[i];
                data[i] = data[j];
                data[j] = temp;
                i++;
                j--;
            }
        } while (i <= j);

        if (left < j) Quick_Sort(data, left, j);
        if (i < right) Quick_Sort(data, i, right);
    }


    static void Main()
    {

        //Read text files

        string[] Day = System.IO.File.ReadAllLines("Day.txt");
        string[] Date = System.IO.File.ReadAllLines("Date.txt");
        string[] _Open = System.IO.File.ReadAllLines("SH1_Open.txt");
        string[] _Close = System.IO.File.ReadAllLines("SH1_Close.txt");
        string[] _Diff = System.IO.File.ReadAllLines("SH1_Diff.txt");
        string[] _Volume = System.IO.File.ReadAllLines("SH1_Volume.txt");

        //Convert to double Array

        //double[] Dates = Array.ConvertAll(Date, s => double.Parse(s));
        double[] SH1_Open = Array.ConvertAll(_Open, s => double.Parse(s));
        double[] SH1_Close = Array.ConvertAll(_Close, s => double.Parse(s));
        double[] SH1_Diff = Array.ConvertAll(_Diff, s => double.Parse(s));
        double[] SH1_Volume = Array.ConvertAll(_Volume, s => double.Parse(s));


        Console.WriteLine("
Welcome to Shane Porter's Algorithms and Complexity Assingment!

What would you like to do?"
);
        Console.WriteLine("
1. Select an individual array to analyse

2. View all of the files in decending order by Date

3. Search for a Date

4. Search for a Day
       
5. Sort an Array"
);

        int Choice = Convert.ToInt32(Console.ReadLine());



        //Option 1. Individual Array
        if (Choice == 1)

        Console.WriteLine("
You have chosen to select an individual array to analyse"
);
        Console.WriteLine("
Please select the array that you wish to analyse"
);
        Console.WriteLine("
1. Day
2. Date
3. SH1_Open
4. SH1_Close
5. SH1_Diff
6. SH1_Volume"
);

        int ArrayChoice = Convert.ToInt32(Console.ReadLine());

        //Day
        if (ArrayChoice == 1)


        //Date
        if (ArrayChoice == 2)
        {

            DateTime[] dates = new DateTime[143];
            dates[0] = Convert.ToDateTime("12/01/2009");
            dates[1] = DateTime.Now;

            Console.WriteLine(Date);


        }

        //SH1_Open
        if (ArrayChoice == 3)
        {
            Quick_Sort(SH1_Open, 0, 143);
            for (int i = 0; i < SH1_Open.Length; i++)
            {
                Console.WriteLine(SH1_Open[i]);
            }

        }
        //SH1_Close
        if (ArrayChoice == 4)
        {
            Quick_Sort(SH1_Close, 0, 143);
            for (int i = 0; i < SH1_Close.Length; i++)
            {
                Console.WriteLine(SH1_Close[i]);
            }

            //SH1_Diff
            if (ArrayChoice == 5)
            {
                Quick_Sort(SH1_Diff, 0, 143);
                for (int i = 0; i < SH1_Diff.Length; i++)
                {
                    Console.WriteLine(SH1_Diff[i]);
                }
            }
        }

        //SH1_Volume
        if (ArrayChoice == 6)
        {
            Quick_Sort(SH1_Volume, 0, 143);
            for (int i = 0; i < SH1_Volume.Length; i++)
            {
                Console.WriteLine(SH1_Volume[i]);
            }
        }






    }
}

}

我希望输出如下:星期一星期一星期一星期二星期二星期二等

非常感谢您的帮助!谢谢您。


根据您的示例,在我看来,最简单的方法是将数据映射到double类型,对其进行排序,然后再映射回来。像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Dictionary<string, double> dayToDouble = new Dictionary<string, double>()
{
    {"Monday", 0.0 },
    {"Tuesday", 1.0 },
    {"Wednesday", 2.0 },
    {"Thursday", 3.0 },
    {"Friday", 4.0 },
    {"Saturday", 5.0 },
    {"Sunday", 6.0 }
};
Dictionary<double, string> doubleToDay =
    dayToDouble.ToDictionary(kvp => kvp.Value, kvp => kvp.Key);

double[] Days = Day.Select(day => dayToDouble[day]).ToArray();

然后,您可以像往常一样对Days进行排序,并在显示结果时将其映射回来:

1
2
3
4
5
Quick_Sort(Days, 0, Days.Length);
foreach (double dayValue in Days)
{
    Console.WriteLine(doubleToDay[dayValue]);
}

< BR>我认为以上应该解决您的具体要求,即使用您的Quick_Sort()方法对一周中的几天进行排序。但是,请注意,要使用这种方法,您必须有一种方法将所有数据映射到double和后面。这可能是可行的,也可能不总是可行的,或者至少不方便。

虽然一周中的几天没有现成的可比较的表示(即,您总是需要以某种方式将它们映射到可比较的数据类型),但除double之外,其他许多类型都有。如果总是到处映射数据值以便对其进行排序,那就太可惜了。

幸运的是,.NET(和许多其他框架)通过拥有彼此"可比较"的数据类型概念,能够很好地处理这一问题。在.NET中,这是使用IComparable接口完成的,这些接口类型如stringDateTime、数字类型等都实现了。

要使用它,您需要使您的Quick_Sort()方法成为泛型方法,在IComparable的类型参数上指定一个约束,以便在排序方法中使用CompareTo()方法。将这种方法应用到您的方法中,会出现如下情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public static void Quick_Sort<T>(T[] data, int left, int right)
    where T : IComparable<T>
{
    T temp;
    int i, j;
    T pivot;
    i = left;
    j = right;
    pivot = data[(left + right) / 2];
    do
    {
        while ((data[i].CompareTo(pivot) < 0) && (i < right)) i++;
        while ((pivot.CompareTo(data[j]) < 0) && (j > left)) j--;
        if (i <= j)
        {
            temp = data[i];
            data[i] = data[j];
            data[j] = temp;
            i++;
            j--;
        }
    } while (i <= j);

    if (left < j) Quick_Sort(data, left, j);
    if (i < right) Quick_Sort(data, i, right);
}

然后,您应该能够调用输入数组是实现IComparable的任何类型的方法,而不仅仅是double。例如,DateTime

1
double[] Dates = Array.ConvertAll(Date, s => DateTime.Parse(s));

然后您可以像对其他数组那样调用它:

1
Quick_Sort(Dates, 0, Dates.Length);

在.NET中还有其他与比较相关的类型。除了IComparable外,上述两种常见的替代方法(通常在许多类中都支持)是IComparer接口和Comparison谓词类型。您将允许调用者传入这些类型的实例,而不是用作方法的约束。这两种方法都可以让传入的对象负责比较一对值。


这看起来像是一个家庭作业):在C中,有内置的快速排序算法实现-Array.Sort()-您可能会注意到本机的快速排序算法是通用的-即,只要您的元素实现接口IComparable,它就可以工作-因此,您可以从中获得灵感,并将您的双专用快速排序重写为通用的(spoilerS-完整代码如下)。

至于一周中的排序天数,现在当您有快速排序的通用版本时,可以使用系统枚举DayOfWeek

1
2
var days = Array.ConvertAll(Day, s => (DayOfWeek)Enum.Parse(typeof(DayOfWeek), s));
Quick_Sort(days, 0, days.Length - 1);

注意:DayOfWeek使用英文日历顺序(星期日是一周的第一天);如果您想要不同的顺序,您必须自己创建枚举-并在那里指定正确的值。像:

1
2
3
4
public enum MyDayOfWeek : int {
  Monday = 0,
  Tuesday = 1, // etc
}

常规快速排序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static void Quick_Sort<T>(T[] data, int left, int right) where T : IComparable {
  T temp;
  int i, j;
  T pivot;
  i = left;
  j = right;
  pivot = data[(left + right) / 2];
  do {
    while ((data[i].CompareTo(pivot) < 0) && (i < right)) i++;
    while ((pivot.CompareTo(data[j]) < 0) && (j > left)) j--;
    if (i <= j) {
      temp = data[i];
      data[i] = data[j];
      data[j] = temp;
      i++;
      j--;
    }
  } while (i <= j);

  if (left < j) Quick_Sort(data, left, j);
  if (i < right) Quick_Sort(data, i, right);
}