Skip to content

Instantly share code, notes, and snippets.

@maheshj01
Last active November 5, 2023 00:19
Show Gist options
  • Save maheshj01/f90fe4bda1fed746b7f194168bd78720 to your computer and use it in GitHub Desktop.
Save maheshj01/f90fe4bda1fed746b7f194168bd78720 to your computer and use it in GitHub Desktop.
algorithm to sort the books using the Library of Congress col numbers
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);
}
@maheshj01
Copy link
Author

First Two terms compared so far

@maheshj01
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment