Skip to content

Instantly share code, notes, and snippets.

@Carolusian
Created July 17, 2014 08:16
Show Gist options
  • Save Carolusian/3530a9d60cbc25fb1953 to your computer and use it in GitHub Desktop.
Save Carolusian/3530a9d60cbc25fb1953 to your computer and use it in GitHub Desktop.
List imap mail folders with parent and child relationship
/**
* List the with parent and child relationship
*/
object ImapFolders extends App {
val folders = List(
"mail201.udomain.com.hk.Winway",
"mail201.udomain.com.hk.Winway.Quota",
"mail201.udomain.com.hk.Winway.Delivery",
"mail201.udomain.com.hk.Winway.PO",
"mail201.udomain.com.hk.UA",
"mail201.udomain.com.hk.UA.Haha",
"mail201.udomain.com.hk.UA.Lala",
"mail201.udomain.com.hk.UA.Lala.A",
"mail201.udomain.com.hk.UA.Lala.B",
"mail201.udomain.com.hk.UA.Vendor",
"mail201.udomain.com.hk.UA.Vendor.RSI",
"mail201.udomain.com.hk.UA.Vendor.American Phil",
"mail201.udomain.com.hk.UA.Vendor.American Phil.PO",
"mail201.udomain.com.hk.UA.Vendor.SCI",
"mail201.udomain.com.hk.UA.Color",
"mail201.udomain.com.hk.Excellent",
"mail201.udomain.com.hk.Excellent.PO",
"mail201.udomain.com.hk.Excellent.Quote",
"mail201.udomain.com.hk.Maker",
"mail201.udomain.com.hk.Maker.Maker Factory",
"mail201.udomain.com.hk.Champion",
"mail201.udomain.com.hk.Champion.Order",
"mail201.udomain.com.hk.Champion.Quote",
"mail201.udomain.com.hk.Champion.Delivery",
"mail201.udomain.com.hk.TAL",
"mail201.udomain.com.hk.TAL.Order",
"mail201.udomain.com.hk.TAL.Quote",
"mail201.udomain.com.hk.TAL.Account",
"mail201.udomain.com.hk.GPSS",
"mail201.udomain.com.hk.Sent Messages",
"mail201.udomain.com.hk.HSBC",
"mail201.udomain.com.hk.Drafts",
"mail201.udomain.com.hk.Other Factory",
"mail201.udomain.com.hk.Deleted Message",
"Outbox",
"Spam",
"Draft",
"Trash",
"OldInbox",
"INBOX"
)
//!--NOTE--
//The gist divide the following steps into two steps for better illustration
//Actually, step 1 and 2 can be merged together...
// Step 1:
// Find grouped folders foreach elemented
// If the size of a group is one, this means its group member is itself
val groupedFolders =
folders map (x => findGroup(x, folders))
//groups which have children
val groupsWithChildren = groupedFolders filter (_.length > 1)
// Check whether any group it is a child of other groups.
// If yes, remove it
val uniqueGroupedFolders = groupedFolders filter { x =>
//Loop though all groupsWithChildren
//Check if any of them contains x,
// If x is contained in subgroups,
// need to remove x in this group to avoid duplication
if(inSubgroup(x, groupsWithChildren)) false
else true
}
uniqueGroupedFolders foreach (println)
println(uniqueGroupedFolders(6))
println("-------------------------------")
// Step 2:
// For each group whose member size is larger than 3,
// we need to do similar stuffs recursively since subgroup may exist
val groupedResult = uniqueGroupedFolders map { grp =>
if(grp.length >= 3)
divideSubgroup(grp, 0)
else
grp
}
groupedResult foreach println
def divideSubgroup(group: List[String], level:Int):List[Any] = {
//Remeber that the first elem is parent, So start with the second elem
val subGroup = group.tail
val grpedFolders = subGroup map (x => findGroup(x, subGroup))
val grpsWithChildren = grpedFolders filter (_.length > 1)
val uniqueGrpedFolders = grpedFolders filter { x =>
if(inSubgroup(x, grpsWithChildren)) false
else true
}
//If the group size is 1, means no subgroup
val children = uniqueGrpedFolders filter (_.length == 1)
//If the group size > 2, means it is a potential subgroup
val potentialSubgroups = uniqueGrpedFolders filter (_.length > 1)
val result:List[Any] = (group.head :: children.map(_.head))
if(!potentialSubgroups.isEmpty)
potentialSubgroups.foldLeft(result) { (r, sub) =>
r ::: List(divideSubgroup(sub, level + 1))
}
else
result
}
def inSubgroup(elem:List[String], haystack:List[List[String]]):Boolean = {
for(compare <- haystack) {
if(compare.length > elem.length
&& compare.toSet.intersect(elem.toSet) == elem.toSet)
return true
}
return false
}
def findGroup(elem: String, haystack: List[String]):List[String] = {
//Find all elements startWith "elem." in "haystack"
//e.g. if "elem" is "mail201.udomain.com.hk.TAL",
//then mail201.udomain.com.hk.TAL.Order and similar items should be
//returned
return elem :: haystack.filter(_.startsWith(s"$elem."))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment