Last active
November 5, 2023 00:19
-
-
Save maheshj01/f90fe4bda1fed746b7f194168bd78720 to your computer and use it in GitHub Desktop.
algorithm to sort the books using the Library of Congress col numbers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:math'; | |
void main() { | |
/// Enter list of LCNumbers to sort in quotes ("") separated by comma (,) | |
List<Book> books = <String>[ | |
"GN799.A41 H6 2017", | |
"PQ4843.O53 G313", | |
"CR6005.O35 L3 1954", | |
"GN799.A41 H6 1937", | |
"ZR605.A35 H5 1979", | |
"AR6005.A37 H5 1979", | |
"PR6005.A357 H5 1979", | |
"PR6005.A357 H5 1979", | |
"KR6005 357 H5 1979", | |
"C3 .A40", | |
"C25 .C25", | |
"C124 .D45" | |
] | |
.map( | |
(e) => Book( | |
title: "The Lord of the Rings", | |
author: "J.R.R. Tolkien", | |
lcCallNumber: e), | |
) | |
.toList(); | |
List<Book> unSortedBooks = List.from(books); | |
// [ | |
// Book( | |
// title: "The Lord of the Rings", | |
// author: "J.R.R. Tolkien", | |
// lcCallNumber: "CR6005.O35 L3 1954", | |
// ), | |
// Book( | |
// title: "The Hobbit", | |
// author: "J.R.R. Tolkien", | |
// lcCallNumber: "AR005.A35 H6 1937", | |
// ), | |
// Book( | |
// title: "The Hitchhiker's Guide to the Galaxy", | |
// author: "Douglas Adams", | |
// lcCallNumber: "AR6005.A35 H5 1979", | |
// ), | |
// Book( | |
// title: "The Hitchhiker's Guide to the Galaxy", | |
// author: "Douglas Adams", | |
// lcCallNumber: "AR6005.A357 H5 1979", | |
// ), | |
// Book( | |
// title: "The Hitchhiker's Guide to the Galaxy", | |
// author: "Douglas Adams", | |
// lcCallNumber: "AR6005 357 H5 1979", | |
// ), | |
// ]; | |
// Sort the list of books by their LC call numbers. | |
books.sort((a, b) => a.compareTo(b)); | |
// // Print the list of books in sorted order. | |
print("********** Sorted LC call numbers ************"); | |
print("\n"); | |
print(" Rank | Old Rank | LCCallNumber"); | |
print("---------------------------------------------"); | |
for (int i = 0; i < books.length; i++) { | |
int index = unSortedBooks.indexOf(books[i]); | |
print(" $i. | $index | ${books[i].lcCallNumber}"); | |
print("---------------------------------------------"); | |
} | |
} | |
class Book { | |
String? title; | |
String? author; | |
String lcCallNumber; | |
Book({this.title, this.author, required this.lcCallNumber}); | |
} | |
extension BookCompare on Book { | |
/// Returns a negative value if this is ordered | |
/// before book2, a positive value if this is ordered | |
/// after book2, or zero if this and other | |
/// are equivalent. | |
int compareTo(Book book2) { | |
final lcCallSplitRegExp = RegExp(r"[.\s]"); | |
String lc1 = lcCallNumber; // GN799.A41 H6 2017 | |
String lc2 = book2.lcCallNumber; // GN799.A41 H6 1937 | |
List<String> list1 = lc1.split(lcCallSplitRegExp).toList(); | |
List<String> list2 = lc2.split(lcCallSplitRegExp).toList(); | |
int len1 = list1.length; | |
int len2 = list2.length; | |
for (int i = 0; i < min(len1, len2); i++) { | |
String line1 = list1[i]; | |
String line2 = list2[i]; | |
if (line1 == line2) | |
continue; | |
else { | |
/// first line and different | |
if (i == 0) { | |
return secondLineCompare(list1[i], list2[i]); | |
} | |
/// second line is not equal | |
else if (i == 1) { | |
final secondLineLc1 = list1[i]; // A41 | |
final secondLineLc2 = list2[i]; // A41 | |
final secondLineResult = | |
secondLineCompare(secondLineLc1, secondLineLc2); | |
return secondLineResult; | |
} else { | |
/// some line > 1 is not equal | |
if (list1[i].isNumeric() && !list2[i].isNumeric()) { | |
return -1; | |
} else if (!list1[i].isNumeric() && list2[i].isNumeric()) { | |
return -1; | |
} else { | |
final num1 = double.parse(list1[i]); | |
final num2 = double.parse(list2[i]); | |
return num1.compareTo(num2); | |
} | |
} | |
} | |
} | |
/// both numbers are equal | |
return 0; | |
} | |
} | |
extension NumerCompare on String { | |
bool isNumeric() { | |
// Check if the string is empty. | |
if (isEmpty) { | |
return false; | |
} | |
bool result = true; | |
// Check if the string contains only digits. | |
for (int i = 0; i < length; i++) { | |
if (!this[i].isDigit()) { | |
return false; | |
} | |
} | |
// The string is a number. | |
return result; | |
} | |
bool isDigit() { | |
return codeUnitAt(0) >= 48 && codeUnitAt(0) <= 57; | |
} | |
} | |
final letterAndNumberSplitRegExp = RegExp(r'(?<=[A-Za-z])(?=[0-9])'); | |
/// Comparator for firstLine in the LCNumber | |
/// AR005 AND AR6005 | |
// returns -1 | |
int alphaNumericCompare(String a, String b) { | |
List<String> aSplitList = a.split(letterAndNumberSplitRegExp); //AR 005 | |
List<String> bSplitList = b.split(letterAndNumberSplitRegExp); // AR 6005 | |
final letter1 = aSplitList[0]; // AR | |
final letter2 = bSplitList[0]; // AR | |
final result = letter1.compareTo(letter2); | |
if (result != 0) { | |
return result; | |
} else { | |
/// if letter is same | |
final number1 = double.parse(aSplitList[1]); | |
/// 005 | |
final number2 = double.parse(bSplitList[1]); | |
/// 6005 | |
int numberResult = number1.compareTo(number2); | |
if (numberResult != 0) { | |
return numberResult; | |
} else { | |
/// terms are equal | |
return 0; | |
} | |
} | |
} | |
/// c85 H2 | |
/// c85 h20 | |
int secondLineCompare(String a, String b) { | |
/// letter has preference over number | |
/// e.g .H345 and 13 in | |
/// AR6005 .H345 vs AR6005 13 | |
bool startsWithLetter1 = RegExp(r'^[A-Za-z]').hasMatch(a); | |
// Check if the second string starts with a letter. | |
bool startsWithLetter2 = RegExp(r'^[A-Za-z]').hasMatch(b); | |
// If the first string starts with a letter and the second string does not, return the first string. | |
if (startsWithLetter1 && !startsWithLetter2) { | |
return -1; | |
} | |
// If the second string starts with a letter and the first string does not, return the second string. | |
if (!startsWithLetter1 && startsWithLetter2) { | |
return 1; | |
} | |
/// Both start with letter | |
/// make string lengths equal by appending zeros | |
/// for easy comparison using alphaNumericCompare | |
int length1 = a.length; | |
int length2 = b.length; | |
// If the lengths are not the same, then find the smaller string. | |
String smallerString = a; | |
String largerString = b; | |
if (length1 > length2) { | |
smallerString = a; | |
largerString = b; | |
} | |
// Append 0 to the smaller string until it has the same length as the larger string. | |
while (smallerString.length < largerString.length) { | |
smallerString += "0"; | |
} | |
a = smallerString; | |
b = largerString; | |
return alphaNumericCompare(a, b); | |
} |
Sorting based on the rules at https://www.library.kent.edu/university-libraries/library-congress-tutorial-call-number-and-shelving
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
First Two terms compared so far