//task 8 and task 9 /// <summary> /// Load the selected dataset /// </summary> /// <param name="selection">Number 1-3 corresponding to a dataset choice</param> /// <returns>The loaded dataset</returns> private static SeismicRecord[] loadDataset(int selection) { switch (selection) { case 2: //dataset 2 populateArraysTwo(); return(fillRecordArray()); case 3: //task 9 //both datasets populateArraysOne(); SeismicRecord[] first = fillRecordArray(); populateArraysTwo(); SeismicRecord[] second = fillRecordArray(); //concatenate the datasets into a single array SeismicRecord[] output = new SeismicRecord[first.Length + second.Length]; first.CopyTo(output, 0); second.CopyTo(output, first.Length); return(output); default: //dataset 1 populateArraysOne(); return(fillRecordArray()); } }
/// <summary> /// Populate an array from the global data arrays /// </summary> /// <returns>An array of SeismicRecord objects</returns> private static SeismicRecord[] fillRecordArray() { SeismicRecord[] data = new SeismicRecord[year.Length]; for (int i = 0; i < year.Length; i++) { data[i] = new SeismicRecord(year[i], month[i], day[i], time[i], mag[i], lat[i], lon[i], depth[i], region[i], id[i], timestamp[i]); } return(data); }
/// <summary> /// Binary search for multiple values using leftmost and rightmost insertion point binary searches /// </summary> /// <param name="data">data to search</param> /// <param name="value">value to search for</param> /// <param name="searchProperty">property to search in</param> /// <param name="steps">reference to steps counter</param> /// <returns>An array of matches</returns> public static SeismicRecord[] binarySearchForMultiple(SeismicRecord[] data, object value, PropertyInfo searchProperty, ref int steps) { int lower = binarySearchLeft(data, value, searchProperty, ref steps); int upper = binarySearchRight(data, value, searchProperty, ref steps); SeismicRecord[] output = new SeismicRecord[(upper - lower)]; Array.Copy(data, lower, output, 0, upper - lower); return(output); }
//task 2 /// <summary> /// Start the sorting process /// Ask user to choose an algorithm and order /// </summary> /// <param name="dataSelected">data column to sort by</param> /// <param name="data">data to sort</param> /// <returns>Sorted data array</returns> private static SeismicRecord[] sortSelectedData(string dataSelected, SeismicRecord[] data) { Console.Clear(); //get user choice of algorithm Console.WriteLine("Which sorting algorithm do you want to use?"); Console.WriteLine("\t1:\tQuick Sort\n\t2:\tMerge Sort\n\t3:\tInsertion Sort\n\t4:\tHeap Sort\n\t5:\tBubble Sort\n"); int algoSelection = getUserInput(1, 5); //get user choice of order Console.WriteLine("\tHow do you want to sort this data?"); Console.WriteLine("\t\t1:\tAscending order\n\t\t2:\tDescending order\n"); int selection = getUserInput(1, 2); //sort with chosen algorithm SeismicRecord[] sortedData = new SeismicRecord[data.Length]; switch (algoSelection) { case 1: sortedData = quickSortData(data, dataSelected); break; case 2: sortedData = mergeSortData(data, dataSelected); break; case 3: sortedData = insertionSortData(data, dataSelected); break; case 4: sortedData = heapSortData(data, dataSelected); break; case 5: sortedData = bubbleSortData(data, dataSelected); break; } //return sorted data, if neccessary reverse order first switch (selection) { case 2: //reverse the ascending order array to get a decending order one SeismicRecord[] output = new SeismicRecord[sortedData.Length]; int count = 0; for (int i = sortedData.Length - 1; i >= 0; i--) { output[count] = (SeismicRecord)sortedData[i].Clone(); count++; } return(output); default: return(sortedData); } }
/// <summary> /// Output a single record /// </summary> /// <param name="record">Record to output</param> private static void outputCurrentState(SeismicRecord record) { //write to html SeismicRecord[] temp = new SeismicRecord[1]; temp[0] = record; writeToHTMLFile(temp); //headers Console.WriteLine("\t{0,-5}\t|\t{1,-10}\t|\t{2,-4}\t|\t{3,-10}\t|\t{4,-15}\t|\t{5,-10}\t|\t{6,-10}\t|\t{7,-10}\t|\t{8,-25}\t|\t{9,-10}\t|\t{10,-25}", "YEAR", "MONTH", "DAY", "TIME", "MAGNITUDE", "LATITUDE", "LONGITUDE", "DEPTH (km)", "REGION", "IRIS ID", "TIMESTAMP"); //data Console.WriteLine("\t{0,-5}\t|\t{1,-10}\t|\t{2,-4}\t|\t{3,-10}\t|\t{4,-15}\t|\t{5,-10}\t|\t{6,-10}\t|\t{7,-10}\t|\t{8,-25}\t|\t{9,-10}\t|\t{10,-25}", record.Year, record.getMonth(), record.getDay(), record.Time, record.Magnitude, record.Lat, record.Lon, record.Depth, record.Region, record.ID, record.Timestamp); }
/// <summary> /// Use a linear type search to go through the entire array and find the highest value /// </summary> /// <param name="data">data to search through</param> /// <param name="searchProperty">property to search in</param> /// <returns>A record with maximum value</returns> public static SeismicRecord findMaximumValue(SeismicRecord[] data, PropertyInfo searchProperty) { //validate data first if (data.Length <= 0) { throw new Exception("Data cannot be empty"); } //highest found so far variable SeismicRecord currentMax = data[0]; //iterate through entire array for (int i = 1; i < data.Length; i++) { if (searchProperty.PropertyType == typeof(int)) { int a = (int)searchProperty.GetValue(data[i]); int b = (int)searchProperty.GetValue(currentMax); //is this item bigger than the current max? if (a > b) { //yes, set it as the new current max currentMax = data[i]; } } else if (searchProperty.PropertyType == typeof(string)) { string a = (string)searchProperty.GetValue(data[i]); string b = (string)searchProperty.GetValue(currentMax); if (string.Compare(a, b) > 0) { currentMax = data[i]; } } else if (searchProperty.PropertyType == typeof(decimal)) { decimal a = (decimal)searchProperty.GetValue(data[i]); decimal b = (decimal)searchProperty.GetValue(currentMax); if (a > b) { currentMax = data[i]; } } else if (searchProperty.PropertyType == typeof(long)) { long a = (long)searchProperty.GetValue(data[i]); long b = (long)searchProperty.GetValue(currentMax); if (a > b) { currentMax = data[i]; } } } return(currentMax); }
/// <summary> /// Clone an array of SeismicRecord to avoid reference issues /// </summary> /// <param name="data">data to clone</param> /// <returns>A shallow copy of the data</returns> private static SeismicRecord[] cloneArray(SeismicRecord[] data) { SeismicRecord[] clone = new SeismicRecord[data.Length]; int count = 0; foreach (SeismicRecord s in data) { clone[count] = (SeismicRecord)s.Clone(); count++; } return(clone); }
/// <summary> /// Perform a linear search /// </summary> /// <param name="data">data to search through</param> /// <param name="dataSelection">data column to search</param> /// <returns>A matching record or null if a match cannot be found</returns> private static SeismicRecord linearSearchForOne(SeismicRecord[] data, string dataSelection) { Console.Write("\nEnter your search term: "); string input = Console.ReadLine(); int steps = 0; //timing measurment DateTime start = DateTime.Now; //search SeismicRecord result = Searching.linearSearchForOne(data, input, data[0].GetType().GetProperty(dataSelection), ref steps); //timing measurement DateTime end = DateTime.Now; Console.WriteLine("\nFound in {0} steps using linear search\nTime elapsed: {1}ms", steps, (end - start).TotalMilliseconds); return(result); }
/// <summary> /// sorts the heap into parent nodes higher than children /// </summary> /// <typeparam name="T">Generic type</typeparam> /// <param name="region">region to sort</param> /// <param name="HeapSize">the size of the array</param> /// <param name="Index">where to point</param> /// <param name="properyField">by which property to sort</param> private static void Max_Heapify <T>(RecordCollection region, int HeapSize, int Index, Func <SeismicRecord, T> properyField) where T : IComparable { int Left = (Index + 1) * 2 - 1; int Right = (Index + 1) * 2; int largest = 0; //sorting ascendingly if (region.SortOrder) { //when the left node from the middle is more than indexed node if (Left < HeapSize && properyField(region.Records[Left]).CompareTo(properyField(region.Records[Index])) > 0) { largest = Left; //set largest index } else { largest = Index; } if (Right < HeapSize && properyField(region.Records[Right]).CompareTo(properyField(region.Records[largest])) > 0) { largest = Right; } } //sorting descendingly else { if (Left < HeapSize && properyField(region.Records[Left]).CompareTo(properyField(region.Records[Index])) < 0) { largest = Left; } else { largest = Index; } if (Right < HeapSize && properyField(region.Records[Right]).CompareTo(properyField(region.Records[largest])) < 0) { largest = Right; } } if (largest != Index) { SeismicRecord temp = region.Records[Index]; region.Records[Index] = region.Records[largest]; region.Records[largest] = temp; Max_Heapify(region, HeapSize, largest, properyField); } }
public static string formatPrinter <T>(string paramName, SeismicRecord record, Func <SeismicRecord, T> property) { //unique cases where formatting has to differ switch (paramName) { case "magnitude": return(string.Format("{0:N3}", property(record))); case "longitude": return(string.Format("{0:N3}", property(record))); case "latitude": return(string.Format("{0:N3}", property(record))); case "depth": return(string.Format("{0:N3}", property(record))); case "month": return(string.Format("{0}", record.Month[1])); default: return(string.Format("{0}", property(record))); } }
/// <summary> /// Heap algorithm transform the records into a heap and sorts it logarithmically /// </summary> /// <typeparam name="T">Generic type</typeparam> /// <param name="region">The data to be sorted</param> /// <param name="properyField">Property to sort</param> public static void HeapSort <T>(RecordCollection region, Func <SeismicRecord, T> properyField) where T : IComparable { int HeapSize = region.Records.currentCapacity; int i; //starting from the middle for (i = (HeapSize) / 2; i >= 0; i--) { //create a max heap (sorted) Max_Heapify(region, HeapSize, i, properyField); } for (i = region.Records.currentCapacity - 1; i > 0; i--) { SeismicRecord temp = region.Records[i]; region.Records[i] = region.Records[0]; region.Records[0] = temp; HeapSize--; Max_Heapify(region, HeapSize, 0, properyField); } }
/// <summary> /// Remove an item at the specified index from the array /// </summary> /// <param name="index">Index to remove</param> /// <param name="inputArray">Array to remove from</param> /// <returns>An array without the specified element</returns> private static SeismicRecord[] removeAt(int index, SeismicRecord[] inputArray) { //create a new array of size one less than inputArray size SeismicRecord[] output = new SeismicRecord[inputArray.Length - 1]; int count = 0; //iterate through the source array for (int i = 0; i < inputArray.Length; i++) { //is the index of the source array the index to be removed? if (i != index) { //no, copy from source array to destination array output[count] = (SeismicRecord)inputArray[i].Clone(); count++; } } //return destination array return(output); }
/// <summary> /// Heap sort the data /// Space Complexity: O(1) /// Time Complexity: /// Best: O(nlog(n)) /// Average: O(nlog(n)) /// Worst: O(nlog(n)) /// </summary> /// <param name="data">Data to be sorted</param> /// <param name="sortProperty">Property to sort by</param> /// <param name="steps">reference to step counter</param> public static void heapSort(ref SeismicRecord[] data, PropertyInfo sortProperty, ref int steps) { //build max heap int heapSize = data.Length - 1; for (int j = (heapSize / 2) - 1; j >= 0; j--) { MaxHeapify(ref data, heapSize, j, sortProperty, ref steps); } //sort heap for (int i = data.Length - 1; i > 0; i--) { //swap SeismicRecord temp = data[i]; data[i] = data[0]; data[0] = temp; heapSize--; MaxHeapify(ref data, heapSize, 0, sortProperty, ref steps); } }
/// <summary> /// Merge sort an array of SeismicRecord based on a particular property /// Space complexity: O(n) /// Time complexity: /// Best: O(nlog(n)) /// Average: O(nlog(n)) /// Worst: O(nlog(n)) /// </summary> /// <param name="data">The unsorted array</param> /// <param name="sortProperty">Property to sort by</param> /// <param name="steps">The number of steps taken to sort</param> /// <returns>A sorted array</returns> public static SeismicRecord[] mergeSort(SeismicRecord[] data, PropertyInfo sortProperty, ref int steps) { //array has been divided as much as possible if (data.Length <= 1) { return(data); } //find midpoint index int middleIndex = (data.Length) / 2; SeismicRecord[] left = new SeismicRecord[middleIndex]; SeismicRecord[] right = new SeismicRecord[data.Length - middleIndex]; //divide the source array into two arrays of roughly equal size Array.Copy(data, left, middleIndex); Array.Copy(data, middleIndex, right, 0, right.Length); //merge sort each of the halves left = mergeSort(left, sortProperty, ref steps); right = mergeSort(right, sortProperty, ref steps); //merge the arrays back together in order return(merge(left, right, sortProperty, ref steps)); }
/// <summary> /// Bubble sorts data /// Space complexity: O(1) /// Time complexity: /// Best: O(n) /// Average: O(n^2) /// Worst: O(n^2) /// </summary> /// <param name="data">Data to sort</param> /// <param name="sortProperty">Property to sort by</param> /// <param name="steps">reference to step counter</param> /// <returns>Sorted array</returns> public static SeismicRecord[] bubbleSort(SeismicRecord[] data, PropertyInfo sortProperty, ref int steps) { bool isSorted; for (int i = 0; i < data.Length - 1; i++) { isSorted = true; for (int j = 0; j < data.Length - 1 - i; j++) { steps++; if (sortProperty.PropertyType == typeof(int)) { int a = (int)sortProperty.GetValue(data[j + 1]); int b = (int)sortProperty.GetValue(data[j]); if (a < b) { //swap SeismicRecord temp = data[j]; data[j] = data[j + 1]; data[j + 1] = temp; isSorted = false; } } else if (sortProperty.PropertyType == typeof(string)) { string a = (string)sortProperty.GetValue(data[j + 1]); string b = (string)sortProperty.GetValue(data[j]); if (string.Compare(a, b) < 0) { //swap SeismicRecord temp = data[j]; data[j] = data[j + 1]; data[j + 1] = temp; isSorted = false; } } else if (sortProperty.PropertyType == typeof(decimal)) { decimal a = (decimal)sortProperty.GetValue(data[j + 1]); decimal b = (decimal)sortProperty.GetValue(data[j]); if (a < b) { //swap SeismicRecord temp = data[j]; data[j] = data[j + 1]; data[j + 1] = temp; isSorted = false; } } else if (sortProperty.PropertyType == typeof(long)) { long a = (long)sortProperty.GetValue(data[j + 1]); long b = (long)sortProperty.GetValue(data[j]); if (a < b) { //swap SeismicRecord temp = data[j]; data[j] = data[j + 1]; data[j + 1] = temp; isSorted = false; } } else if (sortProperty.PropertyType == typeof(DateTime)) { DateTime a = (DateTime)sortProperty.GetValue(data[j + 1]); DateTime b = (DateTime)sortProperty.GetValue(data[j]); if (a < b) { //swap SeismicRecord temp = data[j]; data[j] = data[j + 1]; data[j + 1] = temp; isSorted = false; } } } if (isSorted) { break; } } return(data); }
/// <summary> /// Insertion sort data /// Space complexity: O(1) /// Time complexity: /// Best: O(n) /// Average: O(n^2) /// Worst: O(n^2) /// </summary> /// <param name="data">data to sort</param> /// <param name="sortProperty">property to sort by</param> /// <param name="steps">reference to step counter</param> /// <returns>A sorted array</returns> public static SeismicRecord[] insertionSort(SeismicRecord[] data, PropertyInfo sortProperty, ref int steps) { //iterate through the array for (int i = 1; i < data.Length; i++) { SeismicRecord temp = data[i]; int j = i - 1; //repeat until the element is sorted while (j >= 0) { steps++; if (sortProperty.PropertyType == typeof(int)) { int a = (int)sortProperty.GetValue(data[j]); int b = (int)sortProperty.GetValue(temp); if (a > b) { //swap data[j + 1] = data[j]; j--; } else { break; } } else if (sortProperty.PropertyType == typeof(string)) { string a = (string)sortProperty.GetValue(data[j]); string b = (string)sortProperty.GetValue(temp); if (string.Compare(a, b) > 0) { //swap data[j + 1] = data[j]; j--; } else { break; } } else if (sortProperty.PropertyType == typeof(decimal)) { decimal a = (decimal)sortProperty.GetValue(data[j]); decimal b = (decimal)sortProperty.GetValue(temp); if (a > b) { //swap data[j + 1] = data[j]; j--; } else { break; } } else if (sortProperty.PropertyType == typeof(long)) { long a = (long)sortProperty.GetValue(data[j]); long b = (long)sortProperty.GetValue(temp); if (a > b) { //swap data[j + 1] = data[j]; j--; } else { break; } } else if (sortProperty.PropertyType == typeof(DateTime)) { DateTime a = (DateTime)sortProperty.GetValue(data[j]); DateTime b = (DateTime)sortProperty.GetValue(temp); if (a > b) { //swap data[j + 1] = data[j]; j--; } else { break; } } data[j + 1] = temp; } } return(data); }
/// <summary> /// Array partition used by quick sort /// </summary> /// <param name="data">Array</param> /// <param name="low">low index pointer</param> /// <param name="high">high index pointer</param> /// <param name="sortProperty">Property to sort by</param> /// <returns>Partition point index</returns> private static int partition(ref SeismicRecord[] data, int low, int high, PropertyInfo sortProperty, ref int steps) { SeismicRecord pivot = data[high]; int i = low - 1; for (int j = low; j < high; j++) { steps++; //determine how to cast and compare the values if (sortProperty.PropertyType == typeof(string)) { string a = (string)sortProperty.GetValue(data[j]); string b = (string)sortProperty.GetValue(pivot); if (string.Compare(a, b) <= 0) { i++; //swap SeismicRecord temp = (SeismicRecord)data[i].Clone(); data[i] = data[j]; data[j] = temp; } } else if (sortProperty.PropertyType == typeof(int)) { int a = (int)sortProperty.GetValue(data[j]); int b = (int)sortProperty.GetValue(pivot); if (a <= b) { i++; //swap SeismicRecord temp = (SeismicRecord)data[i].Clone(); data[i] = data[j]; data[j] = temp; } } else if (sortProperty.PropertyType == typeof(decimal)) { decimal a = (decimal)sortProperty.GetValue(data[j]); decimal b = (decimal)sortProperty.GetValue(pivot); if (a <= b) { i++; //swap SeismicRecord temp = (SeismicRecord)data[i].Clone(); data[i] = data[j]; data[j] = temp; } } else if (sortProperty.PropertyType == typeof(long)) { long a = (long)sortProperty.GetValue(data[j]); long b = (long)sortProperty.GetValue(pivot); if (a <= b) { i++; //swap SeismicRecord temp = (SeismicRecord)data[i].Clone(); data[i] = data[j]; data[j] = temp; } } else if (sortProperty.PropertyType == typeof(DateTime)) { DateTime a = (DateTime)sortProperty.GetValue(data[j]); DateTime b = (DateTime)sortProperty.GetValue(pivot); if (a <= b) { i++; //swap SeismicRecord temp = (SeismicRecord)data[i].Clone(); data[i] = data[j]; data[j] = temp; } } } //swap SeismicRecord temp2 = (SeismicRecord)data[i + 1].Clone(); data[i + 1] = data[high]; data[high] = temp2; return(i + 1); }
/// <summary> /// Merge two sorted arrays into one sorted array /// </summary> /// <param name="a">Array one</param> /// <param name="b">Array two</param> /// <param name="sortProperty">Property to sort by</param> /// <returns>A Sorted array</returns> private static SeismicRecord[] merge(SeismicRecord[] a, SeismicRecord[] b, PropertyInfo sortProperty, ref int steps) { ArrayList c = new ArrayList(); //repeat until either array a or array b is empty while (a.Length > 0 && b.Length > 0) { steps++; //determine how to cast and compare the values if (sortProperty.PropertyType == typeof(int)) { int itemA = (int)sortProperty.GetValue(a[0]); int itemB = (int)sortProperty.GetValue(b[0]); if (itemA > itemB) { c.Add(b[0].Clone()); b = removeAt(0, b); } else { c.Add(a[0].Clone()); a = removeAt(0, a); } } else if (sortProperty.PropertyType == typeof(string)) { string itemA = (string)sortProperty.GetValue(a[0]); string itemB = (string)sortProperty.GetValue(b[0]); if (string.Compare(itemA, itemB) > 0) { c.Add(b[0].Clone()); b = removeAt(0, b); } else { c.Add(a[0].Clone()); a = removeAt(0, a); } } else if (sortProperty.PropertyType == typeof(decimal)) { decimal itemA = (decimal)sortProperty.GetValue(a[0]); decimal itemB = (decimal)sortProperty.GetValue(b[0]); if (itemA > itemB) { c.Add(b[0].Clone()); b = removeAt(0, b); } else { c.Add(a[0].Clone()); a = removeAt(0, a); } } else if (sortProperty.PropertyType == typeof(long)) { long itemA = (long)sortProperty.GetValue(a[0]); long itemB = (long)sortProperty.GetValue(b[0]); if (itemA > itemB) { c.Add(b[0].Clone()); b = removeAt(0, b); } else { c.Add(a[0].Clone()); a = removeAt(0, a); } } else if (sortProperty.PropertyType == typeof(DateTime)) { DateTime itemA = (DateTime)sortProperty.GetValue(a[0]); DateTime itemB = (DateTime)sortProperty.GetValue(b[0]); if (itemA > itemB) { c.Add(b[0].Clone()); b = removeAt(0, b); } else { c.Add(a[0].Clone()); a = removeAt(0, a); } } } //repeat until array a is empty while (a.Length > 0) { steps++; c.Add(a[0].Clone()); a = removeAt(0, a); } //repeat until array b is empty while (b.Length > 0) { steps++; c.Add(b[0].Clone()); b = removeAt(0, b); } //convert c to an array and avoid null references by cloning SeismicRecord[] output = new SeismicRecord[c.Count]; int count = 0; foreach (SeismicRecord s in c) { output[count] = (SeismicRecord)s.Clone(); count++; } return(output); }
/// <summary> /// Entry point for searching /// </summary> /// <param name="selection">How the user wants to search</param> /// <param name="data">data to search</param> private static void handleSearch(int selection, SeismicRecord[] data) { switch (selection) { case 1: //task 3 //search for one date SeismicRecord result = findADate(data); if (result != null) { //output the result outputCurrentState(result); } else { Console.WriteLine("No record with this date exists."); } break; case 2: //task 4 //search by month SeismicRecord[] result2 = findAMonth(data); if (result2 != null) { //output the result outputCurrentState(result2); } else { Console.WriteLine("No records exist for this month."); } break; case 3: //custom search //get data column to search through string dataSelection = selectDataToAnalyse("search through"); Console.Clear(); //get how the user wants to search int searchType = searchTypeChoice(); switch (searchType) { case 1: //linear for one SeismicRecord result3 = linearSearchForOne(data, dataSelection); if (result3 != null) { //output result outputCurrentState(result3); } else { Console.WriteLine("No result found."); } break; case 2: //binary search SeismicRecord result4 = binarySearchForOne(data, dataSelection); if (result4 != null) { //output result outputCurrentState(result4); } else { Console.WriteLine("No result found."); } break; case 3: //linear for multiple SeismicRecord[] result5 = linearSearchForMultiple(data, dataSelection); if (result5 != null) { //output result outputCurrentState(result5); } else { Console.WriteLine("No results found."); } break; case 4: //binary for multiple SeismicRecord[] result6 = binarySearchForMultiple(data, dataSelection); if (result6 != null && result6.Length > 0) { //output result outputCurrentState(result6); } else { Console.WriteLine("No results found."); } break; } break; } }
/// <summary> /// Initializes the ArrayList from the I/O files, does so by reading selected region files into string[] dictionary, /// then loops through each file name string key, access string[] value by row index and set the temp record through setter dictionary /// once looped though each file, the temp record is fully initialized, so it's added to the array /// </summary> /// <param name="dataSet">Allows user to choose which region to initialize</param> public void InitializeCollections(int dataSet) { /* a look up dictionary for the initializer * Key is the parsed variable from the txt file, Action is a simple delegate which takes 2 arguments; * SesmicRecord and String to perform property assignment operation */ var setters = new Dictionary <string, Action <SeismicRecord, string> > { /*using lambda expressions to assign values to keys. * in parenthesis i call for anonymoius lambda operator (type SesmicRecord) with a value argument */ ["Year"] = (record, value) => record.Year = int.Parse(value), //in this half It initialize the corresponding field of the anonymous property ["Month"] = (record, value) => { //Parses month strings to their integer equivalent into first array sloth for month to sort of give integer weight for the associated string record.Month[0] = DateTime.ParseExact(value.TrimEnd(' '), "MMMM", CultureInfo.InvariantCulture) .Month.ToString(); //trimmed the end spaces, otherwise it won't recognize it's a month record.Month[1] = value.TrimEnd(' ').ToUpper(); //sets the string equivalent to the month }, ["Day"] = (record, value) => record.Day = int.Parse(value), ["Time"] = (record, value) => record.Time = DateTime.ParseExact(value, "HH:mm:ss", CultureInfo.InvariantCulture).TimeOfDay, ["Magnitude"] = (record, value) => record.Magnitude = double.Parse(value), ["Latitude"] = (record, value) => record.Latitude = double.Parse(value), ["Longitude"] = (record, value) => record.Longitude = double.Parse(value), ["Depth"] = (record, value) => record.Depth = double.Parse(value), ["Region"] = (record, value) => record.Region = value, ["IRIS_ID"] = (record, value) => record.Iris_id = int.Parse(value), ["Timestamp"] = (record, value) => record.Timestamp = int.Parse(value), //conversion of values is necessary as the stream reads everything as a string. }; DirectoryInfo dataColumns = new DirectoryInfo(@"SesmicData\"); FileInfo[] Files = dataColumns.GetFiles($"*{dataSet}.txt"); Console.WriteLine($"Initializing region {dataSet}\n"); Dictionary <string, string[]> lines = new Dictionary <string, string[]>(); /*reading files is a very slow operation, so it's best to read all the text from the file and put it in an array * the string array can later be indexed by row to create a record which will be added to an array */ foreach (FileInfo file in Files) { lines.Add(file.Name, File.ReadAllLines(file.FullName)); } int row = 0; /*the condition compares current row with the overall length of string array entries * array is quadratic, so it's safe to assume all the files will have same (n) entries*/ while (row < lines[$"Day_{dataSet}.txt"].Length) { //temprory record to store values from string arrays SeismicRecord temp = new SeismicRecord(); //looping through each key in the dictionary foreach (KeyValuePair <string, string[]> file in lines) { /* retrieves the file name index (in this case it's to get the length) at a point _1 or _2 is deteccted * Day_1 will return pos. 3 (the pos. at which $"_{dataSet}" detected is at 3 */ int pos = file.Key.IndexOf($"_{dataSet}"); //delegate Action <SeismicRecord, string> fieldSetter; //if the pos -1 then indexOf couldn't retrieve the position, or if trying to retrieve the said substring from setter returns false if (pos < 0 || !setters.TryGetValue(file.Key.Substring(0, pos), out fieldSetter)) { //if either condition is true, skip this iteration continue; } else { //if the substring is retrievable initialize the temp with the value in a current indexed row fieldSetter(temp, file.Value[row]); } } /*once the foreach loop is completed, the temp will have all of its fields initialized * so the next step is to add the temp to the array and increment the index for next row*/ Records.AddRecord(temp); row++; } }
/// <summary> /// Sub routine for Heap sort. Arranges the data into a heap structure /// </summary> /// <param name="data">Data array</param> /// <param name="heapSize">number of items in the heap</param> /// <param name="index">halfway point index</param> /// <param name="sortProperty">property to sort by</param> /// <param name="steps">reference to step counter</param> private static void MaxHeapify(ref SeismicRecord[] data, int heapSize, int index, PropertyInfo sortProperty, ref int steps) { int left = (2 * (index + 1)) - 1; int right = 2 * (index + 1); int largest = index; steps++; if (sortProperty.PropertyType == typeof(int)) { if (left < heapSize) { int a = (int)sortProperty.GetValue(data[left]); int b = (int)sortProperty.GetValue(data[index]); if (a > b) { largest = left; } } else { largest = index; } if (right < heapSize) { int a = (int)sortProperty.GetValue(data[right]); int b = (int)sortProperty.GetValue(data[largest]); if (a > b) { largest = right; } } } else if (sortProperty.PropertyType == typeof(string)) { if (left < heapSize) { string a = (string)sortProperty.GetValue(data[left]); string b = (string)sortProperty.GetValue(data[index]); if (string.Compare(a, b) > 0) { largest = left; } } else { largest = index; } if (right < heapSize) { string a = (string)sortProperty.GetValue(data[right]); string b = (string)sortProperty.GetValue(data[largest]); if (string.Compare(a, b) > 0) { largest = right; } } } else if (sortProperty.PropertyType == typeof(decimal)) { if (left < heapSize) { decimal a = (decimal)sortProperty.GetValue(data[left]); decimal b = (decimal)sortProperty.GetValue(data[index]); if (a > b) { largest = left; } } else { largest = index; } if (right < heapSize) { decimal a = (decimal)sortProperty.GetValue(data[right]); decimal b = (decimal)sortProperty.GetValue(data[largest]); if (a > b) { largest = right; } } } else if (sortProperty.PropertyType == typeof(long)) { if (left < heapSize) { long a = (long)sortProperty.GetValue(data[left]); long b = (long)sortProperty.GetValue(data[index]); if (a > b) { largest = left; } } else { largest = index; } if (right < heapSize) { long a = (long)sortProperty.GetValue(data[right]); long b = (long)sortProperty.GetValue(data[largest]); if (a > b) { largest = right; } } } else if (sortProperty.PropertyType == typeof(DateTime)) { if (left < heapSize) { DateTime a = (DateTime)sortProperty.GetValue(data[left]); DateTime b = (DateTime)sortProperty.GetValue(data[index]); if (a > b) { largest = left; } } else { largest = index; } if (right < heapSize) { DateTime a = (DateTime)sortProperty.GetValue(data[right]); DateTime b = (DateTime)sortProperty.GetValue(data[largest]); if (a > b) { largest = right; } } } if (largest != index) { //swap SeismicRecord temp = data[index]; data[index] = data[largest]; data[largest] = temp; MaxHeapify(ref data, heapSize, largest, sortProperty, ref steps); } }
/// <summary> /// Search through the entire array and return ALL matches /// </summary> /// <param name="data"></param> /// <param name="value"></param> /// <param name="searchProperty"></param> /// <returns></returns> public static SeismicRecord[] linearSearchForMultiple(SeismicRecord[] data, object value, PropertyInfo searchProperty, ref int steps) { //declare array list to store an as-yet unknown number of matches ArrayList matches = new ArrayList(); int numOfMatches = 0; foreach (SeismicRecord s in data) { steps++; if (searchProperty.PropertyType == typeof(int)) { int a = (int)searchProperty.GetValue(s); int b = Convert.ToInt32(value); if (a == b) { //match found, add to arraylist matches.Add(s); numOfMatches++; } } else if (searchProperty.PropertyType == typeof(string)) { string a = (string)searchProperty.GetValue(s); string b = (string)value; if (a == b) { matches.Add(s); numOfMatches++; } } else if (searchProperty.PropertyType == typeof(decimal)) { decimal a = (decimal)searchProperty.GetValue(s); decimal b = 0; decimal.TryParse(value.ToString(), out b); if (a == b) { matches.Add(s); numOfMatches++; } } else if (searchProperty.PropertyType == typeof(long)) { long a = (long)searchProperty.GetValue(s); long b = (long)value; if (a == b) { matches.Add(s); numOfMatches++; } } else if (searchProperty.PropertyType == typeof(DateTime)) { DateTime a = (DateTime)searchProperty.GetValue(s); DateTime b = new DateTime(); DateTime.TryParse(value.ToString(), out b); if (a == b) { matches.Add(s); numOfMatches++; } } } //convert arraylist if (numOfMatches > 0) { //convert arraylist to array to return SeismicRecord[] output = new SeismicRecord[numOfMatches]; int count = 0; foreach (var match in matches) { output[count] = (SeismicRecord)match; count++; } return(output); } else { //no matches, return null return(null); } }