feat: Implement tag combination generation with depth and order constraints
This commit is contained in:
parent
cd27308cfa
commit
2809b6e818
1 changed files with 76 additions and 0 deletions
|
|
@ -92,6 +92,42 @@ pub fn parse_tags(filename: &str) -> Result<(String, Vec<String>, String), Parse
|
|||
Ok((base_name, tags, extension))
|
||||
}
|
||||
|
||||
pub fn create_tag_combinations(tags: &[String], depth: usize) -> Vec<Vec<String>> {
|
||||
let mut result = Vec::new();
|
||||
|
||||
// Handle empty tags or depth 0
|
||||
if tags.is_empty() || depth == 0 {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Add individual tags first
|
||||
for tag in tags {
|
||||
result.push(vec![tag.clone()]);
|
||||
}
|
||||
|
||||
// Generate combinations up to specified depth
|
||||
for len in 2..=depth.min(tags.len()) {
|
||||
let mut temp = Vec::new();
|
||||
|
||||
// Start with existing combinations of length-1
|
||||
for combo in result.iter().filter(|c| c.len() == len - 1) {
|
||||
// Try to add each remaining tag that comes after the last tag in combo
|
||||
if let Some(last) = combo.last() {
|
||||
for tag in tags {
|
||||
if tag > last && !combo.contains(tag) {
|
||||
let mut new_combo = combo.clone();
|
||||
new_combo.push(tag.clone());
|
||||
temp.push(new_combo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result.extend(temp);
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
pub fn filter_tags(current: Vec<String>, remove: &[String]) -> Vec<String> {
|
||||
current.into_iter()
|
||||
.filter(|tag| !remove.contains(tag))
|
||||
|
|
@ -287,4 +323,44 @@ mod tests {
|
|||
let result = filter_tags(current, &remove);
|
||||
assert!(result.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_tag_combinations_empty() {
|
||||
let tags: Vec<String> = vec![];
|
||||
let result = create_tag_combinations(&tags, 2);
|
||||
assert!(result.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_tag_combinations_depth_limit() {
|
||||
let tags = vec!["tag1".to_string(), "tag2".to_string(), "tag3".to_string()];
|
||||
let result = create_tag_combinations(&tags, 2);
|
||||
|
||||
// Should contain individual tags and pairs, but no triples
|
||||
assert!(result.iter().all(|combo| combo.len() <= 2));
|
||||
assert_eq!(result.len(), 6); // 3 individual + 3 pairs
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_tag_combinations_order() {
|
||||
let tags = vec!["tag2".to_string(), "tag1".to_string(), "tag3".to_string()];
|
||||
let result = create_tag_combinations(&tags, 2);
|
||||
|
||||
// Check that all combinations maintain alphabetical order
|
||||
for combo in result {
|
||||
if combo.len() > 1 {
|
||||
assert!(combo.windows(2).all(|w| w[0] < w[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_tag_combinations_uniqueness() {
|
||||
let tags = vec!["tag1".to_string(), "tag2".to_string(), "tag3".to_string()];
|
||||
let result = create_tag_combinations(&tags, 3);
|
||||
|
||||
// Convert to set to check for duplicates
|
||||
let result_set: std::collections::HashSet<_> = result.into_iter().collect();
|
||||
assert_eq!(result_set.len(), 7); // 3 individual + 3 pairs + 1 triple
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue