繁体   English   中英

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

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

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

我猜想我每天都必须分配一个带有if语句的数字,但是我一生都无法理解。

这是我已经做的。 SH1文件正在按照我希望的方式运行。 文本文件只是一长串数字,因此我可以轻松地将它们转换为双精度数字。

至于日子,(还有日期,但我还没写,所以请忽略已经存在的内容,因为它不起作用),我不知道该怎么办。

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






    }
}

}

我希望输出是这样的:星期一星期一星期一星期二星期二星期二等等

任何帮助是极大的赞赏! 谢谢。

这看起来像是一项作业:)在C#中,有内置的Array.Sort()算法实现Array.Sort() -您可能会注意到,本机QuickSort算法是通用的-即只要您的元素实现接口IComparable它就可以工作-因此您可能会从中获得启发,并将您的双倍QuickSort重写为通用代码(扰流板-完整代码如下)。

至于星期几? 现在,当您拥有快速排序的通用版本时,可以使用系统枚举DayOfWeek

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

注意: DayOfWeek使用英语日历顺序(星期日是一周的第一天); 如果您想要不同的顺序,则必须创建自己的枚举-并在其中分配正确的值。 喜欢:

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

通用快速排序:

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

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

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进行排序,并在显示结果时将其映射回去:

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


我认为以上内容应满足您的特定要求,即使用Quick_Sort()方法对一周中的几天进行排序。 但是,请注意,要使用此方法,您必须有一种方法将所有数据映射为double并返回。 这可能或可能并不总是可行的,或者至少是不方便的。

尽管星期几没有可比的表示形式(即,您总是必须以某种方式将它们映射到可比较的数据类型),但是除了double以外,还有许多其他类型。 必须始终围绕映射数据值以便对它们进行排序会很可惜。

幸运的是,.NET(和许多其他框架)通过具有彼此“可比较”的数据类型的概念而优雅地处理了这一问题。 在.NET中,这是使用IComparable<T>接口完成的,该接口都实现了stringDateTime ,数字类型等类型。

要使用此功能,您需要使您的Quick_Sort()方法通用,在IComparable<T>的类型参数上指定一个约束,以便可以在sort方法中使用CompareTo()方法。 将这种方法应用于您的方法,将看起来像这样:

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<T>任何类型而不是double调用该方法。 例如, DateTime

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

然后可以像使用其他数组一样调用它:

Quick_Sort(Dates, 0, Dates.Length);

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

暂无
暂无

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

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