Extracting usernames (mentions) from text is a common task in social media analysis and natural language processing. Typically, a username is defined as a sequence of alphanumeric characters or underscores immediately following an @ symbol.
This guide explains how to parse a string to extract these usernames, filter out invalid entries, and sort them based on their frequency of occurrence without using external libraries like Regex (though Regex is powerful, understanding manual string parsing is a crucial fundamental skill).
The Logic of Extraction
To correctly extract usernames, our algorithm must follow these rules:
- Locate: Find the
@symbol. - Validate: Check the characters immediately following it. A valid username character is usually alphanumeric (
a-z,0-9) or an underscore (_). - Stop: Stop capturing characters as soon as an invalid character (like a space, punctuation, or another
@) is encountered. - Filter: Ignore empty matches (e.g., a standalone
@or@!). - Sort: Remove duplicates from the final list but order them based on how frequently they appeared in the original text.
Step 1: Finding the Position of Mentions
We can traverse the string using Python's string method .find(). This allows us to jump from one @ to the next efficiently.
text = "Hello @User1 and @User2"
at_index = text.find("@")
while at_index != -1:
print(f"Found @ at index: {at_index}")
at_index = text.find("@", at_index + 1)Output:
Found @ at index: 6
Found @ at index: 17Step 2: Validating and Extracting Characters
Once an @ is found, we look at the subsequent characters.
text = "@Valid! @Invalid"
at_index = 0
username = ""
for char in text[at_index + 1:]:
if char.isalnum() or char == "_":
username += char
else:
break # Stop at the first invalid character (like '!' or space)
print(f"Extracted: {username}")Output:
Extracted: ValidStep 3: Sorting by Frequency
The requirement is to return a unique list of usernames, but sorted by how often they appeared in the text (most frequent first).
all_found = ['tutorialreference', 'TutorialReference', 'tutorialreference', 'test']
unique_sorted = sorted(
list(set(all_found)),
key=lambda x: all_found.count(x),
reverse=True
)
print(unique_sorted)Output:
['tutorialreference', 'test', 'TutorialReference']Complete Code Solution
Here is the robust after_at function that implements the logic: locate, extract, validate, and sort.
def after_at(text):
"""
Extracts usernames starting with @ from text.
Valid characters: Alphanumeric and Underscore.
Returns unique list sorted by frequency (descending).
"""
usernames = []
at_index = text.find("@")
while at_index != -1:
username = ""
for char in text[at_index + 1 : ]:
if char.isalnum() or char == "_" or char.isalpha():
username += char
else:
break
if username:
usernames.append(username)
at_index = text.find("@", at_index + 1)
result = sorted(
list(set(usernames)),
key=lambda x: usernames.count(x),
reverse=True
)
return result
if __name__ == "__main__":
print(f"Test 1: {after_at('@TutorialReference @tutorialreference I won in the @ competition')}")
print(f"Test 2: {after_at('@!TutorialReference @tutorialreference I won in the competition')}")
print(f"Test 3: {after_at('I won in the competition@')}")
print(f"Test 4: {after_at('@!@LabETutorialReferencex @tutorialreference I won in the @TutorialReference competition @experiment')}")Execution Output:
Test 1: ['tutorialreference', 'TutorialReference']
Test 2: ['tutorialreference']
Test 3: []
Test 4: ['tutorialreference', 'TutorialReference', 'experiment', 'LabETutorialReferencex']Conclusion
Extracting patterns like usernames manually gives you granular control over what constitutes a "valid" character without relying on complex Regular Expressions.
- Iterate using
.find()to locate delimiters (@). - Validate strictly using
.isalnum()loop logic. - Process the resulting list to filter duplicates and apply custom sorting logic based on frequency.