deep-sort-list-parser 1.0.1__tar.gz → 1.0.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- deep_sort_list_parser-1.0.5/PKG-INFO +66 -0
- deep_sort_list_parser-1.0.5/README.md +56 -0
- deep_sort_list_parser-1.0.5/deep_sort_list.py +114 -0
- deep_sort_list_parser-1.0.5/deep_sort_list_test.py +39 -0
- {deep_sort_list_parser-1.0.1 → deep_sort_list_parser-1.0.5}/pyproject.toml +1 -1
- deep_sort_list_parser-1.0.5/test_suite.py +27 -0
- deep_sort_list_parser-1.0.1/PKG-INFO +0 -63
- deep_sort_list_parser-1.0.1/README.md +0 -53
- deep_sort_list_parser-1.0.1/deep_sort_list.py +0 -83
- deep_sort_list_parser-1.0.1/deep_sort_list_test.py +0 -27
- deep_sort_list_parser-1.0.1/test_suite.py +0 -35
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: deep_sort_list_parser
|
|
3
|
+
Version: 1.0.5
|
|
4
|
+
Summary: A recursive data parser to flatten and sort complex nested structures safely.
|
|
5
|
+
Author: Developer
|
|
6
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Requires-Python: >=3.8
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
11
|
+
# 📦 deep_sort_list_parser
|
|
12
|
+
|
|
13
|
+
A data parsing library designed to safely unwrap, flatten, and sort messy, multi-nested collections (Lists, Tuples, Sets, and Dictionaries) without crashing.
|
|
14
|
+
|
|
15
|
+
## 🌟 Enhanced Features
|
|
16
|
+
- **Infinite Flattening:** Recursively drills through any number of nested list layouts `[[[]]]` to extract loose data.
|
|
17
|
+
- **Advanced Type-Safe Tracking:** Automatically isolates items into distinct sorted categories: Numbers, Words, and Symbols.
|
|
18
|
+
- **Smart Text Analysis:** Intelligently tracks sentences with spaces and punctuation (like `"Hello World!"`) inside the words track instead of breaking them apart.
|
|
19
|
+
- **Boolean Guarding:** Standard booleans (`True` / `False`) are trapped safely and sorted inside the words track instead of corrupting mathematical numbers.
|
|
20
|
+
- **Deep Locker Sorting:** Alphabetizes keys inside nested dictionaries down to any depth while keeping values safely paired. Fully supports specialized dictionaries like `OrderedDict` and `Counter`.
|
|
21
|
+
- **On-the-Fly Conversion:** Dynamically casts numeric text strings (like `'100'`) into math integers upon request.
|
|
22
|
+
|
|
23
|
+
## 🚀 How to Use
|
|
24
|
+
|
|
25
|
+
Save `deep_sort_list.py` in your project folder, import it, and pass your data payload into the `clean_and_flatten` function.
|
|
26
|
+
|
|
27
|
+
### 🔹 Scenario 1: Standard Mixed Input (With Sentences & Booleans)
|
|
28
|
+
You can pass completely mixed lists, nested containers, or even single loose items safely.
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
import deep_sort_list
|
|
32
|
+
|
|
33
|
+
# A chaotic list containing numbers, strings with punctuation, and booleans
|
|
34
|
+
data = [44, [3, "@#%&"], "Hello World!", True]
|
|
35
|
+
|
|
36
|
+
result = deep_sort_list.clean_and_flatten(data)
|
|
37
|
+
|
|
38
|
+
print(result["numbers"]) # [3, 44]
|
|
39
|
+
print(result["words"]) # ['Hello World!', 'True']
|
|
40
|
+
print(result["symbols"]) # ['@#%&']
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 🔹 Scenario 2: Handling Nested Dictionaries (Locker Sorting)
|
|
44
|
+
If your input contains complex dictionary blocks, the engine alphabetizes all internal keys at every sub-layer while keeping values locked to their pairs.
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
nested_data = [{"sex": "Female", "name": {"last": "Singh", "first": "Aadhya"}}]
|
|
48
|
+
|
|
49
|
+
result = deep_sort_list.clean_and_flatten(nested_data)
|
|
50
|
+
print(result["dictionaries"])
|
|
51
|
+
# Output: [{'name': {'first': 'Aadhya', 'last': 'Singh'}, 'sex': 'Female'}]
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 🔹 Scenario 3: Smart Number Conversion
|
|
55
|
+
By default, text digits like `'100'` are kept in the words track. Set `convert_numeric_strings=True` to dynamically convert and sort them as math integers.
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
result = deep_sort_list.clean_and_flatten(data, convert_numeric_strings=True)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## 📊 Return Format
|
|
62
|
+
The function returns a clean Python dictionary with four distinct tracks:
|
|
63
|
+
- `result["numbers"]`: Sorted integers and floats.
|
|
64
|
+
- `result["words"]`: Sorted alphanumeric text words, sentences, and booleans.
|
|
65
|
+
- `result["symbols"]`: Sorted pure punctuation strings (like `@`, `#`, `^`).
|
|
66
|
+
- `result["dictionaries"]`: Isolated dictionary blocks with fully alphabetized internal key layouts.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# 📦 deep_sort_list_parser
|
|
2
|
+
|
|
3
|
+
A data parsing library designed to safely unwrap, flatten, and sort messy, multi-nested collections (Lists, Tuples, Sets, and Dictionaries) without crashing.
|
|
4
|
+
|
|
5
|
+
## 🌟 Enhanced Features
|
|
6
|
+
- **Infinite Flattening:** Recursively drills through any number of nested list layouts `[[[]]]` to extract loose data.
|
|
7
|
+
- **Advanced Type-Safe Tracking:** Automatically isolates items into distinct sorted categories: Numbers, Words, and Symbols.
|
|
8
|
+
- **Smart Text Analysis:** Intelligently tracks sentences with spaces and punctuation (like `"Hello World!"`) inside the words track instead of breaking them apart.
|
|
9
|
+
- **Boolean Guarding:** Standard booleans (`True` / `False`) are trapped safely and sorted inside the words track instead of corrupting mathematical numbers.
|
|
10
|
+
- **Deep Locker Sorting:** Alphabetizes keys inside nested dictionaries down to any depth while keeping values safely paired. Fully supports specialized dictionaries like `OrderedDict` and `Counter`.
|
|
11
|
+
- **On-the-Fly Conversion:** Dynamically casts numeric text strings (like `'100'`) into math integers upon request.
|
|
12
|
+
|
|
13
|
+
## 🚀 How to Use
|
|
14
|
+
|
|
15
|
+
Save `deep_sort_list.py` in your project folder, import it, and pass your data payload into the `clean_and_flatten` function.
|
|
16
|
+
|
|
17
|
+
### 🔹 Scenario 1: Standard Mixed Input (With Sentences & Booleans)
|
|
18
|
+
You can pass completely mixed lists, nested containers, or even single loose items safely.
|
|
19
|
+
|
|
20
|
+
```python
|
|
21
|
+
import deep_sort_list
|
|
22
|
+
|
|
23
|
+
# A chaotic list containing numbers, strings with punctuation, and booleans
|
|
24
|
+
data = [44, [3, "@#%&"], "Hello World!", True]
|
|
25
|
+
|
|
26
|
+
result = deep_sort_list.clean_and_flatten(data)
|
|
27
|
+
|
|
28
|
+
print(result["numbers"]) # [3, 44]
|
|
29
|
+
print(result["words"]) # ['Hello World!', 'True']
|
|
30
|
+
print(result["symbols"]) # ['@#%&']
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 🔹 Scenario 2: Handling Nested Dictionaries (Locker Sorting)
|
|
34
|
+
If your input contains complex dictionary blocks, the engine alphabetizes all internal keys at every sub-layer while keeping values locked to their pairs.
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
nested_data = [{"sex": "Female", "name": {"last": "Singh", "first": "Aadhya"}}]
|
|
38
|
+
|
|
39
|
+
result = deep_sort_list.clean_and_flatten(nested_data)
|
|
40
|
+
print(result["dictionaries"])
|
|
41
|
+
# Output: [{'name': {'first': 'Aadhya', 'last': 'Singh'}, 'sex': 'Female'}]
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### 🔹 Scenario 3: Smart Number Conversion
|
|
45
|
+
By default, text digits like `'100'` are kept in the words track. Set `convert_numeric_strings=True` to dynamically convert and sort them as math integers.
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
result = deep_sort_list.clean_and_flatten(data, convert_numeric_strings=True)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## 📊 Return Format
|
|
52
|
+
The function returns a clean Python dictionary with four distinct tracks:
|
|
53
|
+
- `result["numbers"]`: Sorted integers and floats.
|
|
54
|
+
- `result["words"]`: Sorted alphanumeric text words, sentences, and booleans.
|
|
55
|
+
- `result["symbols"]`: Sorted pure punctuation strings (like `@`, `#`, `^`).
|
|
56
|
+
- `result["dictionaries"]`: Isolated dictionary blocks with fully alphabetized internal key layouts.
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import collections
|
|
2
|
+
|
|
3
|
+
def clean_and_flatten(any_input, convert_numeric_strings = False):
|
|
4
|
+
"""
|
|
5
|
+
Recursively flattens nested data structures and segregates types into sorted streams.
|
|
6
|
+
|
|
7
|
+
This function drills down into infinitely nested lists, tuples, sets, and
|
|
8
|
+
dictionaries. It separates loose elements into type-safe buckets, safely
|
|
9
|
+
alphabetizes internal dictionary configurations without losing key-value mappings,
|
|
10
|
+
and handles booleans and complex strings without pipeline crashes.
|
|
11
|
+
|
|
12
|
+
Parameters:
|
|
13
|
+
-----------
|
|
14
|
+
any_input : any
|
|
15
|
+
The entry-level data element or container (list, tuple, set, dict,
|
|
16
|
+
int, float, bool, or str) to parse.
|
|
17
|
+
convert_numeric_strings : bool, default False
|
|
18
|
+
If True, text strings containing pure digits (e.g., '100') will be
|
|
19
|
+
dynamically converted into integers and sorted into the numbers track.
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
--------
|
|
23
|
+
dict
|
|
24
|
+
A structured dictionary map holding four cleanly sorted data streams:
|
|
25
|
+
- "numbers": Sorted integers and floats.
|
|
26
|
+
- "symbols": Sorted pure punctuation marks.
|
|
27
|
+
- "words": Sorted alphanumeric text strings and standalone booleans.
|
|
28
|
+
- "dictionaries": Sorted dictionaries with internal alphabetical keys.
|
|
29
|
+
"""
|
|
30
|
+
numbers = []
|
|
31
|
+
words = []
|
|
32
|
+
symbols = []
|
|
33
|
+
dict_tracks = []
|
|
34
|
+
|
|
35
|
+
def deep_sort_dict(input_dict):
|
|
36
|
+
"""
|
|
37
|
+
Takes any dictionary, sorts its keys alphabetically,
|
|
38
|
+
and checks if any of its values are ALSO dictionaries to sort them too!
|
|
39
|
+
"""
|
|
40
|
+
sorted_dict = {}
|
|
41
|
+
sorted_keys = sorted(input_dict.keys(), key=str)
|
|
42
|
+
|
|
43
|
+
for key in sorted_keys:
|
|
44
|
+
value = input_dict[key]
|
|
45
|
+
|
|
46
|
+
# Use isinstance to support OrderedDict, Counter, and sub-dicts
|
|
47
|
+
|
|
48
|
+
if isinstance(value, dict): # RECURSION CHECK: If the value inside this key is ANOTHER dictionary,call deep_sort_dict
|
|
49
|
+
sorted_dict[key] = deep_sort_dict(value)
|
|
50
|
+
else:
|
|
51
|
+
sorted_dict[key] = value
|
|
52
|
+
return sorted_dict
|
|
53
|
+
|
|
54
|
+
# HANDLE ACCIDENTAL INPUTS at entry level:
|
|
55
|
+
# Supports custom lists/tuples/sets safely via Sequence checks
|
|
56
|
+
|
|
57
|
+
if isinstance(any_input, (list, tuple, set)):
|
|
58
|
+
any_list = any_input
|
|
59
|
+
else:
|
|
60
|
+
any_list = [any_input]
|
|
61
|
+
|
|
62
|
+
def unpack(box):
|
|
63
|
+
|
|
64
|
+
for item in box:
|
|
65
|
+
if isinstance(item, (list, tuple, set)):
|
|
66
|
+
unpack(item)
|
|
67
|
+
|
|
68
|
+
# Find any dictionary inside the list box
|
|
69
|
+
elif isinstance(item, dict):
|
|
70
|
+
clean_dict = deep_sort_dict(item)
|
|
71
|
+
dict_tracks.append(clean_dict)
|
|
72
|
+
|
|
73
|
+
elif type(item) is bool:
|
|
74
|
+
if item is True:
|
|
75
|
+
words.append("True")
|
|
76
|
+
else:
|
|
77
|
+
words.append("False")
|
|
78
|
+
|
|
79
|
+
elif isinstance(item, (int, float)):
|
|
80
|
+
numbers.append(item)
|
|
81
|
+
|
|
82
|
+
else:
|
|
83
|
+
text_item = str(item)
|
|
84
|
+
|
|
85
|
+
# Smart word evaluation check.
|
|
86
|
+
# If a string has letters or digits (even with spaces/exclamations), it's a word track item.
|
|
87
|
+
# If it is only pure punctuation characters (like "@@@"), it goes to symbols.
|
|
88
|
+
|
|
89
|
+
if any(char.isalnum() for char in text_item):
|
|
90
|
+
if convert_numeric_strings and text_item.isdigit():
|
|
91
|
+
numbers.append(int(text_item))
|
|
92
|
+
else:
|
|
93
|
+
words.append(text_item)
|
|
94
|
+
|
|
95
|
+
else:
|
|
96
|
+
symbols.append(text_item)
|
|
97
|
+
|
|
98
|
+
# Start the engine using the dynamic argument variable
|
|
99
|
+
unpack(any_list)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
# Sort each individual track cleanly
|
|
103
|
+
numbers.sort()
|
|
104
|
+
words.sort()
|
|
105
|
+
symbols.sort()
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
"numbers": numbers,
|
|
109
|
+
"symbols": symbols,
|
|
110
|
+
"words": words,
|
|
111
|
+
"dictionaries": dict_tracks
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import collections
|
|
2
|
+
import deep_sort_list
|
|
3
|
+
|
|
4
|
+
crazy_list = [44, [3, "apple", "@#%&"], {"name": "Aadhya", "sex": "Female", "personal_details": {"is_married": False, "address": {"house_no": 448, "plot_no": 403, "strret": 'abc', "locality": "janki_nagar_extension", "pincode": 452010}, "is_employed": True}, "religion": "Hindu"}, "banana", "100", "^^^", '&', '101','222','1000', 589, [445,[28,'%','828',[45,54],'*']]]
|
|
5
|
+
|
|
6
|
+
my_list = [44, '404', 88, 100, '100', '101', "Shreya@08singh","hey, buddy",'#', '^', {"subject": "english", "marks": {"internal_marks": 75, "internal_marks_2": 88}}, 'bjbj', 22545,[44, '404', 88, 100, '100', '101','#', '^', 'bjbj', 22545, 56, [44, '404', 88, 100, '100', '101','#', '^', 'bjbj', 22545,[44,"Hello David", '404', 88, 100, '100', '101','#', '^', 'bjbj', 22545]]]]
|
|
7
|
+
|
|
8
|
+
print("------Testing List--------")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
print("=== REQUIREMENT 1: Standard Dictionary Return ===")
|
|
12
|
+
result_crazy_list = deep_sort_list.clean_and_flatten(crazy_list)
|
|
13
|
+
result_my_list = deep_sort_list.clean_and_flatten(my_list)
|
|
14
|
+
|
|
15
|
+
print("--- CRAZY LIST ---")
|
|
16
|
+
print("Words:", result_crazy_list["words"])
|
|
17
|
+
print("Numbers:", result_crazy_list["numbers"])
|
|
18
|
+
print("Symbols:", result_crazy_list["symbols"])
|
|
19
|
+
|
|
20
|
+
print("\n--- MY LIST ----")
|
|
21
|
+
print("Words:", result_my_list["words"])
|
|
22
|
+
print("Numbers:", result_my_list["numbers"])
|
|
23
|
+
print("Symbols:", result_my_list["symbols"])
|
|
24
|
+
print("Dictionaries:", result_my_list["dictionaries"])
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
print("=== REQUIREMENT 2: Convert String Numbers to Ints ===")
|
|
28
|
+
r_crazy_list = deep_sort_list.clean_and_flatten(crazy_list, convert_numeric_strings=True)
|
|
29
|
+
r_my_list = deep_sort_list.clean_and_flatten(my_list, convert_numeric_strings=True)
|
|
30
|
+
|
|
31
|
+
print("Words", r_crazy_list["words"])
|
|
32
|
+
print("Numbers", r_crazy_list["numbers"])
|
|
33
|
+
print("Symbols", r_crazy_list["symbols"])
|
|
34
|
+
print("Dictionaries", r_crazy_list["dictionaries"])
|
|
35
|
+
|
|
36
|
+
print("--- MY LIST WITH CONVERSION ON ---")
|
|
37
|
+
print("Words:", r_my_list["words"])
|
|
38
|
+
print("Numbers:", r_my_list["numbers"])
|
|
39
|
+
print("Symbols:", r_my_list["symbols"])
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "deep_sort_list_parser"
|
|
7
|
-
version = "1.0.
|
|
7
|
+
version = "1.0.5"
|
|
8
8
|
description = "A recursive data parser to flatten and sort complex nested structures safely."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# test_suite.py
|
|
2
|
+
import collections
|
|
3
|
+
import deep_sort_list
|
|
4
|
+
|
|
5
|
+
print("Running optimized automated test suite...")
|
|
6
|
+
|
|
7
|
+
# 🔹 1. Test Sentence Spaces and Punctuation (Word vs Symbol Fix)
|
|
8
|
+
mixed_text = ["banana!", "Hello World", "@@@"]
|
|
9
|
+
res1 = deep_sort_list.clean_and_flatten(mixed_text)
|
|
10
|
+
assert res1["words"] == ["Hello World", "banana!"], f"Failed Word Fix: Got {res1['words']}"
|
|
11
|
+
assert res1["symbols"] == ["@@@"], f"Failed Symbol Fix: Got {res1['symbols']}"
|
|
12
|
+
|
|
13
|
+
# 🔹 2. Test Boolean Separation (Boolean Sorting Fix)
|
|
14
|
+
bool_list = [44, True, 0, False, 1]
|
|
15
|
+
res2 = deep_sort_list.clean_and_flatten(bool_list)
|
|
16
|
+
# Booleans should be completely absent from numbers and cleanly isolated in words!
|
|
17
|
+
assert res2["numbers"] == [0, 1, 44], f"Failed Number Separation: Got {res2['numbers']}"
|
|
18
|
+
assert res2["words"] == ["False", "True"], f"Failed Boolean Extraction: Got {res2['words']}"
|
|
19
|
+
|
|
20
|
+
# 🔹 3. Test Specialized Dictionary Support (OrderedDict Fix)
|
|
21
|
+
ordered_data = collections.OrderedDict([("z", 1), ("a", 2)])
|
|
22
|
+
res3 = deep_sort_list.clean_and_flatten(ordered_data)
|
|
23
|
+
# The engine should catch it via isinstance and process it natively into dictionaries!
|
|
24
|
+
assert res3["dictionaries"] == [{"a": 2, "z": 1}], f"Failed Sub-dict Handling: Got {res3['dictionaries']}"
|
|
25
|
+
|
|
26
|
+
print("ALL ARCHITECTURAL PASSES OK!")
|
|
27
|
+
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: deep_sort_list_parser
|
|
3
|
-
Version: 1.0.1
|
|
4
|
-
Summary: A recursive data parser to flatten and sort complex nested structures safely.
|
|
5
|
-
Author: Developer
|
|
6
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
7
|
-
Classifier: Programming Language :: Python :: 3
|
|
8
|
-
Requires-Python: >=3.8
|
|
9
|
-
Description-Content-Type: text/markdown
|
|
10
|
-
|
|
11
|
-
# deep_sort_list
|
|
12
|
-
|
|
13
|
-
A bulletproof data parsing library designed to safely unwrap, flatten, and sort messy, multi-nested collections (Lists and Dictionaries) without crashing.
|
|
14
|
-
|
|
15
|
-
## What This Solves
|
|
16
|
-
Python's native `.sort()` method immediately crashes with a `TypeError` if a list contains mixed data types (like strings and integers together), or if it contains nested structures.
|
|
17
|
-
|
|
18
|
-
This library completely bypasses that limitation by automatically separating elements into distinct, sorted data streams.
|
|
19
|
-
|
|
20
|
-
## 🚀 How to Use
|
|
21
|
-
|
|
22
|
-
Save `deep_sort_list.py` in your project folder, import it, and pass your data payload into the `clean_and_flatten` function.
|
|
23
|
-
|
|
24
|
-
### 🔹 Scenario 1: Sorting a Complex, Mixed Input
|
|
25
|
-
You can pass completely mixed lists, nested sublists, or even single items directly without a crash.
|
|
26
|
-
|
|
27
|
-
```python
|
|
28
|
-
import deep_sort_list
|
|
29
|
-
|
|
30
|
-
# A chaotic list containing numbers, strings, symbols, and nested boxes
|
|
31
|
-
data = [44, [3, "@#%&"], "banana"]
|
|
32
|
-
|
|
33
|
-
result = deep_sort_list.clean_and_flatten(data)
|
|
34
|
-
|
|
35
|
-
print(result["numbers"]) # Output: [3, 44]
|
|
36
|
-
print(result["words"]) # Output: ['banana']
|
|
37
|
-
print(result["symbols"]) # Output: ['@#%&']
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
### 🔹 Scenario 2: Handling Nested Dictionaries (Locker Sorting)
|
|
41
|
-
If your list contains multi-layered dictionaries, the engine digs through every sub-layer, alphabetizes all keys, keeps the values safely locked to their pairs, and puts them into a dedicated track.
|
|
42
|
-
|
|
43
|
-
```python
|
|
44
|
-
nested_data = [{"sex": "Female", "name": {"last": "Singh", "first": "Shreya"}}]
|
|
45
|
-
|
|
46
|
-
result = deep_sort_list.clean_and_flatten(nested_data)
|
|
47
|
-
print(result["dictionaries"])
|
|
48
|
-
# Output: [{'name': {'first': 'Shreya', 'last': 'Singh'}, 'sex': 'Female'}]
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
### 🔹 Scenario 3: Smart Number Conversion
|
|
52
|
-
By default, text digits like `'100'` are kept in the words track. Set `convert_numeric_strings=True` to dynamically convert and sort them as math integers.
|
|
53
|
-
|
|
54
|
-
```python
|
|
55
|
-
result = deep_sort_list.clean_and_flatten(data, convert_numeric_strings=True)
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
## 📊 Return Format
|
|
59
|
-
The function returns a clean Python dictionary with four tracks:
|
|
60
|
-
- `result["numbers"]`: Sorted integers and floats.
|
|
61
|
-
- `result["words"]`: Sorted text strings.
|
|
62
|
-
- `result["symbols"]`: Sorted special punctuation marks (like `@`, `#`, `^`).
|
|
63
|
-
- `result["dictionaries"]`: Deeply key-sorted internal dictionary blocks.
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
# deep_sort_list
|
|
2
|
-
|
|
3
|
-
A bulletproof data parsing library designed to safely unwrap, flatten, and sort messy, multi-nested collections (Lists and Dictionaries) without crashing.
|
|
4
|
-
|
|
5
|
-
## What This Solves
|
|
6
|
-
Python's native `.sort()` method immediately crashes with a `TypeError` if a list contains mixed data types (like strings and integers together), or if it contains nested structures.
|
|
7
|
-
|
|
8
|
-
This library completely bypasses that limitation by automatically separating elements into distinct, sorted data streams.
|
|
9
|
-
|
|
10
|
-
## 🚀 How to Use
|
|
11
|
-
|
|
12
|
-
Save `deep_sort_list.py` in your project folder, import it, and pass your data payload into the `clean_and_flatten` function.
|
|
13
|
-
|
|
14
|
-
### 🔹 Scenario 1: Sorting a Complex, Mixed Input
|
|
15
|
-
You can pass completely mixed lists, nested sublists, or even single items directly without a crash.
|
|
16
|
-
|
|
17
|
-
```python
|
|
18
|
-
import deep_sort_list
|
|
19
|
-
|
|
20
|
-
# A chaotic list containing numbers, strings, symbols, and nested boxes
|
|
21
|
-
data = [44, [3, "@#%&"], "banana"]
|
|
22
|
-
|
|
23
|
-
result = deep_sort_list.clean_and_flatten(data)
|
|
24
|
-
|
|
25
|
-
print(result["numbers"]) # Output: [3, 44]
|
|
26
|
-
print(result["words"]) # Output: ['banana']
|
|
27
|
-
print(result["symbols"]) # Output: ['@#%&']
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
### 🔹 Scenario 2: Handling Nested Dictionaries (Locker Sorting)
|
|
31
|
-
If your list contains multi-layered dictionaries, the engine digs through every sub-layer, alphabetizes all keys, keeps the values safely locked to their pairs, and puts them into a dedicated track.
|
|
32
|
-
|
|
33
|
-
```python
|
|
34
|
-
nested_data = [{"sex": "Female", "name": {"last": "Singh", "first": "Shreya"}}]
|
|
35
|
-
|
|
36
|
-
result = deep_sort_list.clean_and_flatten(nested_data)
|
|
37
|
-
print(result["dictionaries"])
|
|
38
|
-
# Output: [{'name': {'first': 'Shreya', 'last': 'Singh'}, 'sex': 'Female'}]
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
### 🔹 Scenario 3: Smart Number Conversion
|
|
42
|
-
By default, text digits like `'100'` are kept in the words track. Set `convert_numeric_strings=True` to dynamically convert and sort them as math integers.
|
|
43
|
-
|
|
44
|
-
```python
|
|
45
|
-
result = deep_sort_list.clean_and_flatten(data, convert_numeric_strings=True)
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
## 📊 Return Format
|
|
49
|
-
The function returns a clean Python dictionary with four tracks:
|
|
50
|
-
- `result["numbers"]`: Sorted integers and floats.
|
|
51
|
-
- `result["words"]`: Sorted text strings.
|
|
52
|
-
- `result["symbols"]`: Sorted special punctuation marks (like `@`, `#`, `^`).
|
|
53
|
-
- `result["dictionaries"]`: Deeply key-sorted internal dictionary blocks.
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
def clean_and_flatten(any_input, convert_numeric_strings = False):
|
|
2
|
-
"""
|
|
3
|
-
Flattens any list and returns a DICTIONARY of sorted tracks.
|
|
4
|
-
If convert_numeric_strings is True, text like '100' becomes an integer.
|
|
5
|
-
"""
|
|
6
|
-
numbers = []
|
|
7
|
-
words = []
|
|
8
|
-
symbols = []
|
|
9
|
-
|
|
10
|
-
dict_tracks = []
|
|
11
|
-
|
|
12
|
-
# THE FIX FOR ACCIDENTAL INPUTS:
|
|
13
|
-
# If the user passed a single item (not a list and not a dict),
|
|
14
|
-
# wrap it inside a list box automatically so the loop doesn't crash!
|
|
15
|
-
|
|
16
|
-
if type(any_input) is list:
|
|
17
|
-
any_list = any_input
|
|
18
|
-
else:
|
|
19
|
-
any_list = [any_input]
|
|
20
|
-
|
|
21
|
-
def unpack(box):
|
|
22
|
-
|
|
23
|
-
for item in box:
|
|
24
|
-
if type(item) is list:
|
|
25
|
-
unpack(item)
|
|
26
|
-
|
|
27
|
-
# Find any dictionary inside the list box
|
|
28
|
-
elif type(item) is dict:
|
|
29
|
-
def deep_sort_dict(input_dict):
|
|
30
|
-
"""
|
|
31
|
-
Takes any dictionary, sorts its keys alphabetically,
|
|
32
|
-
and checks if any of its values are ALSO dictionaries to sort them too!
|
|
33
|
-
"""
|
|
34
|
-
sorted_dict = {}
|
|
35
|
-
|
|
36
|
-
sorted_keys = sorted(input_dict.keys(), key=str) # Grab all keys and sort them alphabetically
|
|
37
|
-
|
|
38
|
-
for key in sorted_keys:
|
|
39
|
-
value = input_dict[key]
|
|
40
|
-
|
|
41
|
-
# RECURSION CHECK: If the value inside this key is ANOTHER dictionary,call deep_sort_dict
|
|
42
|
-
if type(value) is dict:
|
|
43
|
-
sorted_dict[key] = deep_sort_dict(value)
|
|
44
|
-
else:
|
|
45
|
-
sorted_dict[key] = value
|
|
46
|
-
|
|
47
|
-
return sorted_dict
|
|
48
|
-
clean_dict = deep_sort_dict(item)
|
|
49
|
-
dict_tracks.append(clean_dict)
|
|
50
|
-
|
|
51
|
-
elif type(item) in (int, float, bool):
|
|
52
|
-
numbers.append(item)
|
|
53
|
-
else:
|
|
54
|
-
text_item = str(item)
|
|
55
|
-
|
|
56
|
-
if text_item.isalnum() == False: # Check for special characters first
|
|
57
|
-
symbols.append(text_item)
|
|
58
|
-
else:
|
|
59
|
-
# User requirement check: Should we turn string numbers into integers?
|
|
60
|
-
if convert_numeric_strings and text_item.isdigit():
|
|
61
|
-
numbers.append(int(text_item))
|
|
62
|
-
else:
|
|
63
|
-
words.append(text_item)
|
|
64
|
-
|
|
65
|
-
# Start the engine using the dynamic argument variable
|
|
66
|
-
unpack(any_list)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
# Sort each individual track cleanly
|
|
70
|
-
numbers.sort()
|
|
71
|
-
words.sort()
|
|
72
|
-
symbols.sort()
|
|
73
|
-
|
|
74
|
-
# RETURN A DICTIONARY: This hands the clean data back to the user!
|
|
75
|
-
|
|
76
|
-
return {
|
|
77
|
-
"numbers": numbers,
|
|
78
|
-
"symbols": symbols,
|
|
79
|
-
"words": words,
|
|
80
|
-
"dictionaries": dict_tracks
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import deep_sort_list
|
|
2
|
-
|
|
3
|
-
crazy_list = [44, [3, "apple", "@#%&"], {"name": "Aadhya", "sex": "Female", "personal_details": {"is_married": False, "address": {"house_no": 448, "plot_no": 403, "strret": 'abc', "locality": "janki_nagar_extension", "pincode": 452010}, "is_employed": True}, "religion": "Hindu"}, "banana", "100", "^^^", '&', '101','222','1000', 589, [445,[28,'%','828',[45,54],'*']]]
|
|
4
|
-
|
|
5
|
-
my_list = [44, '404', 88, 100, '100', '101','#', '^', {"subject": "english", "marks": {"internal_marks": 75, "internal_marks_2": 88}}, 'bjbj', 22545,[44, '404', 88, 100, '100', '101','#', '^', 'bjbj', 22545, 56, [44, '404', 88, 100, '100', '101','#', '^', 'bjbj', 22545,[44, '404', 88, 100, '100', '101','#', '^', 'bjbj', 22545]]]]
|
|
6
|
-
|
|
7
|
-
print("------Testing List--------")
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
print("=== REQUIREMENT 1: Standard Dictionary Return ===")
|
|
11
|
-
result_crazy_list = deep_sort_list.clean_and_flatten(crazy_list)
|
|
12
|
-
result_my_list = deep_sort_list.clean_and_flatten(my_list)
|
|
13
|
-
|
|
14
|
-
print("Words", result_crazy_list["words"])
|
|
15
|
-
print("Numbers", result_crazy_list["numbers"])
|
|
16
|
-
print("Symbols", result_crazy_list["symbols"])
|
|
17
|
-
print("Dictionaries", result_crazy_list["dictionaries"])
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
print("=== REQUIREMENT 1: Convert String Numbers to Ints ===")
|
|
21
|
-
r_crazy_list = deep_sort_list.clean_and_flatten(crazy_list, convert_numeric_strings=True)
|
|
22
|
-
r_my_list = deep_sort_list.clean_and_flatten(my_list, convert_numeric_strings=True)
|
|
23
|
-
|
|
24
|
-
print("Words", r_crazy_list["words"])
|
|
25
|
-
print("Numbers", r_crazy_list["numbers"])
|
|
26
|
-
print("Symbols", r_crazy_list["symbols"])
|
|
27
|
-
print("Dictionaries", r_crazy_list["dictionaries"])
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import deep_sort_list
|
|
2
|
-
|
|
3
|
-
print("Running automated test suite...")
|
|
4
|
-
|
|
5
|
-
# 🔹 Scenario 1: Standalone Single Input (The entryway protection check)
|
|
6
|
-
res1 = deep_sort_list.clean_and_flatten(8)
|
|
7
|
-
assert res1["numbers"] == [8], f"Failed Scenario 1: Expected [8], got {res1['numbers']}"
|
|
8
|
-
|
|
9
|
-
# 🔹 Scenario 2: Standard Mixed List with Empty Containers & Booleans
|
|
10
|
-
weird_list = [2, [], True, False, "apple"]
|
|
11
|
-
res2 = deep_sort_list.clean_and_flatten(weird_list)
|
|
12
|
-
# Remember: False is 0, True is 1 mathematically!
|
|
13
|
-
assert res2["numbers"] == [False, True, 2], f"Failed Scenario 2 Numbers: Got {res2['numbers']}"
|
|
14
|
-
assert res2["words"] == ["apple"], f"Failed Scenario 2 Words"
|
|
15
|
-
|
|
16
|
-
# 🔹 Scenario 3: String Number Conversion Toggle (True vs False)
|
|
17
|
-
mixed_digits = ["100", "banana", 44]
|
|
18
|
-
|
|
19
|
-
# Test with Conversion OFF (Default)
|
|
20
|
-
res3_off = deep_sort_list.clean_and_flatten(mixed_digits)
|
|
21
|
-
assert res3_off["words"] == ["100", "banana"], "Failed Scenario 3 OFF"
|
|
22
|
-
|
|
23
|
-
# Test with Conversion ON
|
|
24
|
-
res3_on = deep_sort_list.clean_and_flatten(mixed_digits, convert_numeric_strings=True)
|
|
25
|
-
assert res3_on["numbers"] == [44, 100], f"Failed Scenario 3 ON Numbers: Got {res3_on['numbers']}"
|
|
26
|
-
assert res3_on["words"] == ["banana"], "Failed Scenario 3 ON Words"
|
|
27
|
-
|
|
28
|
-
# 🔹 Scenario 4: Deep Multi-Nested Dictionary Locker Sorting
|
|
29
|
-
nested_dict = [{"sex": "Female", "name": {"last": "Singh", "first": "Shreya"}}]
|
|
30
|
-
res4 = deep_sort_list.clean_and_flatten(nested_dict)
|
|
31
|
-
|
|
32
|
-
expected_dict = [{'name': {'first': 'Shreya', 'last': 'Singh'}, 'sex': 'Female'}]
|
|
33
|
-
assert res4["dictionaries"] == expected_dict, f"Failed Scenario 4 Locker Sort"
|
|
34
|
-
|
|
35
|
-
print("ALL SCENARIOS PASSED PERFECTLY! Your library is bulletproof.")
|