简体   繁体   中英

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.

Here is what I have already done. The SH1 files are doing as I want them to. 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).

As for sorting days of week; now when you have generic version of quick sort you can make use of system enum 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); 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. 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:

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. However, note that to use this approach you have to have a way to map all of your data to double and back. 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. 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. In .NET, this is done using the IComparable<T> interface, which types like string , DateTime , the numeric types, etc. all implement.

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. 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 . For example, 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. 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. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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