简体   繁体   English

从文本文件读取并在C#中排序的最佳方法

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

How can I take a string array with unsorted days of the week read from a text and convert it into something that I can use in a sorting algorithm? 如何获取一个星期几未排序的字符串数组,该字符串数组从文本中读取并将其转换为可以在排序算法中使用的东西?

I'm guessing that I will have to assign each day with a number with if statements but I just can't get my head around it for the life of me. 我猜想我每天都必须分配一个带有if语句的数字,但是我一生都无法理解。

Here is what I have already done. 这是我已经做的。 The SH1 files are doing as I want them to. SH1文件正在按照我希望的方式运行。 The text files are simply just a long list of numbers so I can just easily convert them into a double. 文本文件只是一长串数字,因此我可以轻松地将它们转换为双精度数字。

As for the days, (and dates but I'm not on that yet so just ignore what is already there because it's not working) I have no idea what to do. 至于日子,(还有日期,但我还没写,所以请忽略已经存在的内容,因为它不起作用),我不知道该怎么办。

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("\nWelcome to Shane Porter's Algorithms and Complexity Assingment!\n\nWhat would you like to do?");
        Console.WriteLine("\n1. Select an individual array to analyse\n\n2. View all of the files in decending order by Date\n\n3. Search for a Date\n\n4. Search for a Day\n        \n5. Sort an Array");

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



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

        Console.WriteLine("\nYou have chosen to select an individual array to analyse");
        Console.WriteLine("\nPlease select the array that you wish to analyse");
        Console.WriteLine("\n1. Day\n2. Date\n3. SH1_Open\n4. SH1_Close\n5. SH1_Diff\n6. 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]);
            }
        }






    }
}

} }

I would like the output to be like this: Monday Monday Monday Tuesday Tuesday Tuesday etc etc 我希望输出是这样的:星期一星期一星期一星期二星期二星期二等等

Any help is greatly appreciated! 任何帮助是极大的赞赏! Thank you. 谢谢。

This looks like a homework :) in C# there is build-in QuickSort algorithm implementation - Array.Sort() - you may take notice that the native QuickSort algorithm is generic - ie it works as long as your elements implement interface IComparable - so you may take inspiration in that and rewrite your double-only QuickSort to generic one (spoilers - full code below). 这看起来像是一项作业:)在C#中,有内置的Array.Sort()算法实现Array.Sort() -您可能会注意到,本机QuickSort算法是通用的-即只要您的元素实现接口IComparable它就可以工作-因此您可能会从中获得启发,并将您的双倍QuickSort重写为通用代码(扰流板-完整代码如下)。

As for sorting days of week; 至于星期几? now when you have generic version of quick sort you can make use of system enum DayOfWeek : 现在,当您拥有快速排序的通用版本时,可以使用系统枚举DayOfWeek

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

Note: DayOfWeek uses English calendar order (Sunday is first day of week); 注意: DayOfWeek使用英语日历顺序(星期日是一周的第一天); if you want different order you'll have to make your own enum - and assign correct values there. 如果您想要不同的顺序,则必须创建自己的枚举-并在其中分配正确的值。 Like: 喜欢:

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

Generic quick sort: 通用快速排序:

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);
}

Based on your example, it seems to me that the simplest approach would be to map your data to the double type, sort it, and then map back. 根据您的示例,在我看来,最简单的方法是将您的数据映射为double类型,对其进行排序,然后进行映射。 Something like this: 像这样:

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();

Then you can sort Days as usual and map it back as you display the result: 然后,您可以照常对Days进行排序,并在显示结果时将其映射回去:

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


I think the above should address your specific request, ie to sort the days of the week using your Quick_Sort() method. 我认为以上内容应满足您的特定要求,即使用Quick_Sort()方法对一周中的几天进行排序。 However, note that to use this approach you have to have a way to map all of your data to double and back. 但是,请注意,要使用此方法,您必须有一种方法将所有数据映射为double并返回。 This may or may not always be feasible, or at least not convenient. 这可能或可能并不总是可行的,或者至少是不方便的。

While the days of the week don't have a readily-comparable representation (ie you're always going to have to map them in some way to a data type that is comparable), many other types besides double do. 尽管星期几没有可比的表示形式(即,您总是必须以某种方式将它们映射到可比较的数据类型),但是除了double以外,还有许多其他类型。 It would be a shame to have to always go around mapping data values just so you can sort them. 必须始终围绕映射数据值以便对它们进行排序会很可惜。

Fortunately, .NET (and many other frameworks) handle this gracefully, by having the concept of data types that are "comparable" to each other. 幸运的是,.NET(和许多其他框架)通过具有彼此“可比较”的数据类型的概念而优雅地处理了这一问题。 In .NET, this is done using the IComparable<T> interface, which types like string , DateTime , the numeric types, etc. all implement. 在.NET中,这是使用IComparable<T>接口完成的,该接口都实现了stringDateTime ,数字类型等类型。

To use this, you'll want to make your Quick_Sort() method generic, specifying a constraint on the type parameter of IComparable<T> so that you can use the CompareTo() method in your sort method. 要使用此功能,您需要使您的Quick_Sort()方法通用,在IComparable<T>的类型参数上指定一个约束,以便可以在sort方法中使用CompareTo()方法。 Applying that approach to your method, it would look something like this: 将这种方法应用于您的方法,将看起来像这样:

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);
}

Then you should be able to call the method where the input array is any type implementing IComparable<T> , rather than just double . 然后,您应该能够在输入数组是实现IComparable<T>任何类型而不是double调用该方法。 For example, DateTime : 例如, DateTime

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

Then you can call it like you would with the other arrays: 然后可以像使用其他数组一样调用它:

Quick_Sort(Dates, 0, Dates.Length);

There are other comparison-related types in .NET as well. .NET中还有其他与比较相关的类型。 Two common alternatives to the above (often supported in many class in addition to IComparable<T> ) are the IComparer<T> interface, and the Comparison<T> predicate type. 上面两种常见的替代方法( 除了 IComparable<T> 以外,通常在许多类中都受支持)是IComparer<T>接口和Comparison<T>谓词类型。 Rather than being used as a constraint on the method, you would allow the caller to pass in an instance of either of those types. 而不是用作方法的约束,您可以允许调用方传入这些类型中的任何一个的实例。 Either will allow the object passed in to be given the responsibility for comparing a pair of values. 要么允许传入的对象负责比较一对值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM