Some taste of functional programming with groovy – 2

Input file:

Ver Duration	House Number	Ver Description
00:15.00	BP0211T0	FS: NRL: BP: NRL Monday Night With Matty Johns TON 2100 (18/3)
00:30.00	CP32336W	CI-April Highlights
01:00.00	CP32119W	LIF-Property Month 60
00:30.00	CP32134W	EV-RioVAlv SunMar31
00:15.00	CP32139W	OD-Argo Sting15
.......... line break.......................................
01:00.00	CP32144W	OD-Argo 60
00:30.00	CP32145W	OD-Argo
01:00.00	CP32149W	OD-Taken 2 60
00:30.00	CP32151W	OD-Taken 2 30B
01:00.00	CP32153W	OD-End Of Watch 60
00:30.00	CP32154W	OD-End Of Watch
00:30.00	CP32159W	OD-Premium Rush VODPrem
00:15.00	CP32224W	OD-Taken 2 STING 15
00:15.00	CP32225W	OD-End Of Watch STING 15
......................erp----------------------------------------
01:00.00	CP32257W	COM-Good God 27/3 60
01:00.00	CP32263W	SHC-GameThrones 1/4 60
00:30.00	CP32269W	A&E-March Highlights
00:15.00	CP32270W	A&E-Toy Hunters 1/4 15
00:45.00	CP32273W	BI-Gene Simmons 27/3
02:00.00	CP32275W	FX-DaVinciDemon 16/4 2min
01:00.00	CP32276W	FX-DaVinciDemon 16/4 60
00:30.00	CP32277W	FX-DaVincis Demons 16/4
^^^^^^^^^^XXXXXXXXXXX^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
00:30.00	CP32278W	NGC-DoomsdayPreppr 8/4
00:30.00	CP32280W	NGC-ToyotaMegafactr8/4
00:30.00	CP32284W	CSA-Aus Podiatry Assoc
00:30.00	CP32285W	CSA-Aus Medicare LocalAll
00:30.00	CP32286W	CSA-RedCross QLD FloodAp
00:45.00	CP32288W	SOHO-Wentworth 1/5 45
00:15.00	CP32324W	OD-The Master
00:30.00	CP32333W	OD-Nitro Circus
01:00.00	CP32335W	CI-April Highlights 60
00:30.00	CP32337W	A&E-TOy Hunters 2/4
02:00.00	CP32341W	FX0-DaVincis Demons 16/4 2m
01:00.00	CP32343W	FX-DaVincis Demons 16/4 60
00:30.00	CP32349W	NGC-WarHerosSkies 10/4
00:30.00	CP32358W	EV-DonVRig Sunday 14/4
00:30.00	JA0086G2	"^FS: FTB: FSD: A League ""iPad  App"" GEN 2012/13 30"" "
01:00.00	JA0106G1	FTV: GEN: Fuel TV is You 2012-13 V2
00:30.00	JA0249D0	SPD: DRA: Andra Drag Racing WED 2130 EDT 2013
00:15.00	JA0251D1	SPD: SPR: World Series Sprintcars WED 1930 (16/1)
00:30.00	JA0447G0	FTV: SUR: ASP Surfing World Tour (2013)
00:30.00	JA0474G1	^FS: RUN: GEN: Rugby Wrap 2013
00:15.00	JA0528G1	"^FS: FSD: NRL: Supercoach ""Prize"" Generic 2013 15"" "
00:15.00	JA0530G1	"^FS: FSD: GEN: Tipping Generic 2013 15"""
01:00.00	JA0574G1	"FS: AFL Who Ever You Love Image 2013 60"" V2"
00:30.00	JA0575G1	"FS: AFL Who Ever You Love Image 2013 30"" V2"
00:15.00	JA0576G1	"FS: AFL Who Ever You Love Image V1 2013 15"" V2"
00:15.00	JA0577G1	"FS: AFL Who Ever You Love Image V2 2013 15"" V2"
01:00.00	JA0582G1	"FS: AFL: Launch Image Games 60"" V2"
00:15.00	JA0583G0	FTV: SUR: ASP Surfing World Tour (2013) 15'  
00:30.00	JA0586G1	"FS: AFL: Launch Image Games 30"" V2"
01:00.00	JA0587G1	"FS: AFL: Image 2013 ""Great Moments"" 60"" V2"
00:30.00	JA0588G1	"FS: AFL: Image 2013 ""Great Moments"" 30"" V2"
00:15.00	JA0619G1	"FS: AFL Who Ever You Love Image V3 2013 15"" V2"
00:15.00	JA0620G1	"FS: AFL Who Ever You Love Image V4 2013 15"" V2"
00:15.00	JA0621G2	"FS: AFL Who Ever You Love Image V5 2013 15"" V3"
00:30.00	JA0622T0	"FS: AFL: On The Couch Launch TON 2030 (18/03) 30"""
00:30.00	JA0627G3	"^FS: FSD: NRL: Supercoach ""Ennis"" 2013 30"" "
01:00.00	JA0648G0	FTV: GEN: March Highlights GEN (2013) 60' 
00:30.00	JA0652T0	"FS: AFL: Open Mike ""Launch"" MON 2130 (18/03) 30"""
01:00.00	JA0681G0	"FS: AFL: Fox Footy Image ""TALENT"" 2013 60"""
00:30.00	JA0682G0	"FS: AFL: Fox Footy Image ""TALENT"" 2013 30"""
00:30.00	JA0699G1	"FS: AFL Who Ever You Love V2 Image 2013 30"" V2"
00:30.00	JA0702T0	"SPD: NAS: Nascar Sprint Cup ""Bristol"" Rply TON 1930 (18/3)"
00:30.00	JA0704D0	"FS: AFL: 2012 GF Recall Syd v Haw SUN 2030 (24/03) 30"""
00:15.00	JA0705D0	"FS: AFL: 2012 GF Recall Syd v Haw ""GOODES"" SUN 2030 (24/03) 15"" "
00:15.00	JA0706D0	"FS: AFL: 2012 GF Recall Syd v Haw ""MALCESKI"" SUN 2030 (24/03) 15"""
00:15.00	JA0707G1	"FS: AFL Who Ever You Love Image V6 ROO 2013 15"" V2"
00:24.00	JA0710D0	^SPD: MAG: Mobil 1 The Grid WED 1900 (20/3)
00:30.00	JA0750G2	FS: CRK: GEN: Cricket in 2013
00:05.00	JA0751G0	"^FS: NRL: NRL Mag Show 5 seconders GEN ""Matty Johns"" 2013"
00:05.00	JA0753G0	"^FS: NRL: NRL Mag Show 5 seconders GEN ""NRL 360 2013"
00:05.00	JA0754G0	"^FS: NRL: NRL Mag Show 5 seconders GEN ""Sterlo"" 2013"
00:05.00	JA0755D0	^FS: GOL: The Golf Show TUE 1930 5 seconders 2013
00:05.00	JA0769G0	"^FS: GEN: Digital Breath  ""HAL"" 2013 "
00:05.00	JA0770G0	"^FS: GEN: Digital Breath  ""CRK"" 2013"
00:05.00	JA0771G0	"^FS: GEN: Digital Breath  ""EPL"" 2013"
00:05.00	JA0772G0	"^FS: GEN: Digital Breath  ""EPL2"" 2013"
00:05.00	JA0773G0	"^FS: GEN: Digital Breath  ""SOCIAL"" 2013 "
00:05.00	JA0774G0	"^FS: GEN: Digital Breath  ""NRL"" 2013"
00:05.00	JA0775G0	"^FS: GEN: Digital Breath  ""NRL2"" 2013 "
00:05.00	JA0776G0	"^FS: GEN: Digital Breath  ""RUN"" 2013"
00:05.00	JA0777G0	"^FS: GEN: Digital Breath  ""SRUN"" 2013 "
00:05.00	JA0778G0	"^FS: GEN: Digital Breath  ""WEB"" 2013 "
00:05.00	JA0779G0	"^FS: GEN: Digital Breath  ""WEB"" 2013"
00:45.00	JA0780G0	"^FS: GEN: FoxSports Relaunch ""Talent"" 2013"
00:05.00	JA0781G0	"^FS: GEN: Digital Breath  ""Foxtel Go 1"" 2013"
00:05.00	JA0782G0	"^FS: GEN: Digital Breath  ""Foxtel Go2"" 2013 "
01:00.00	JA0786G0	"FS: AFL: Friday Night Ritual 60"""
00:30.00	JA0787G0	"FS: AFL: Friday Night Ritual 30"""
00:30.00	JA0788G0	"FS: AFL: Friday Night Ritual ""Ricciuto"" 30"""
00:15.00	JA0789G0	"FS: AFL: Friday Night Ritual 15"""
00:20.00	JA0790G0	"FS: AFL: Friday Night Ritual ""Healy"" 20"""
00:30.00	JA0820C0	"FS: FTB: Socceroos v Oman CSN (26/3) 30"""
00:10.00	JA0821C0	"FS: FTB: Socceroos v Oman CSN (26/3) 10"""
00:30.00	JA0844G0	FS: RUN: FSD: GEN: Rugby Union  Match Centre 2013
00:30.00	JA0850D0	FS: FTB: HAL WK 26 SAT 1700 (23/3)
00:15.00	JA0851D0	FS: FTB: HAL WK 26 SUN 1630 (24/3)
00:30.00	JA0855D0	FS: FSN: AFL: AFL Pre-Season Show WED 1730 (20/3)
00:30.00	XP006929	FX Ultimate Fighter S17 - Wed 1630
00:30.00	XP006930	LSF-AskTheButcher26/3REV

Requirements:

  • Group the lines by 3 category from Description. Description starts with FS / starts with ^FS / starts with ^OD
  • Next group by time for each description group
  • Output with Line number
  • My beginner Groovy code , I am sure the experts will write it even better, comment for improvement will be very much appreciated!

    def out = new File('c:/dev/test/output.txt')
    out.delete()
    new File('c:/dev/test/input.txt').readLines()
                            .findAll { it ==~ /^\d{2}:.+/ } //only select lines that start with number:
                            .collect { it.split ( /\t/ )} //convert string into array of token
                            .collect { lineItems ->           //add an extra column to determine grouping criteria                                 
                                lineItems + [{
                                        switch(lineItems[2]) {
                                            case ~/"FS:.*/ : 
                                                "FS:"
                                                break
                                            case ~/^"\^FS:.*/ : 
                                                "^FS"
                                                break
                                            case ~/^OD-.*/ :
                                                "OD-"
                                                break
                                            default: 
                                                "IGNORE" 
                                        }
                                    }()]
                            }
                            .findAll {!it[3].startsWith("IGNORE")} //drop the rows which doesn't meet our criteria
                            .groupBy { it[3]}  //group by the grouping category (output -> map[string : list[array]]
                            .collect { 
                                       it.value.groupBy{it[0]}  //for each group of Sports Code, perform another grouping on value list based on the duration and sort by keys
                                      .values() //get the values of the groupped by time map
                                      .collectMany{it} //flattens all the result into a single list preserving the order
                            }
                           .collectMany { it } //flatten to a single list of array
                           .eachWithIndex { item , count ->  out << count + '\t' + item[0..2].join('\t') + '\n\r'}
                          
                          
                           println out.text
    

    I think for people familiar with functional coding concepts like Map/Fold/Reduce, the comments are unnecessary and self explanatory. Again the idea is to transform the input file into the output by applying the functions on them. List / Map are the two very important data structure in functional language and you can do magic with them ! And of course all these wouldn’t be possible without the function block/closures. I can’t wait for Java 8 support for closures.

    Anyway, here is the output:

    0	00:15.00	CP32139W	OD-Argo Sting15
    
    1	00:15.00	CP32224W	OD-Taken 2 STING 15
    
    2	00:15.00	CP32225W	OD-End Of Watch STING 15
    
    3	00:15.00	CP32324W	OD-The Master
    
    4	01:00.00	CP32144W	OD-Argo 60
    
    5	01:00.00	CP32149W	OD-Taken 2 60
    
    6	01:00.00	CP32153W	OD-End Of Watch 60
    
    7	00:30.00	CP32145W	OD-Argo
    
    8	00:30.00	CP32151W	OD-Taken 2 30B
    
    9	00:30.00	CP32154W	OD-End Of Watch
    
    10	00:30.00	CP32159W	OD-Premium Rush VODPrem
    
    11	00:30.00	CP32333W	OD-Nitro Circus
    
    12	00:30.00	JA0086G2	"^FS: FTB: FSD: A League ""iPad  App"" GEN 2012/13 30"" "
    
    13	00:30.00	JA0627G3	"^FS: FSD: NRL: Supercoach ""Ennis"" 2013 30"" "
    
    14	00:15.00	JA0528G1	"^FS: FSD: NRL: Supercoach ""Prize"" Generic 2013 15"" "
    
    15	00:15.00	JA0530G1	"^FS: FSD: GEN: Tipping Generic 2013 15"""
    
    16	00:05.00	JA0751G0	"^FS: NRL: NRL Mag Show 5 seconders GEN ""Matty Johns"" 2013"
    
    17	00:05.00	JA0753G0	"^FS: NRL: NRL Mag Show 5 seconders GEN ""NRL 360 2013"
    
    18	00:05.00	JA0754G0	"^FS: NRL: NRL Mag Show 5 seconders GEN ""Sterlo"" 2013"
    
    19	00:05.00	JA0769G0	"^FS: GEN: Digital Breath  ""HAL"" 2013 "
    
    20	00:05.00	JA0770G0	"^FS: GEN: Digital Breath  ""CRK"" 2013"
    
    21	00:05.00	JA0771G0	"^FS: GEN: Digital Breath  ""EPL"" 2013"
    
    22	00:05.00	JA0772G0	"^FS: GEN: Digital Breath  ""EPL2"" 2013"
    
    23	00:05.00	JA0773G0	"^FS: GEN: Digital Breath  ""SOCIAL"" 2013 "
    
    24	00:05.00	JA0774G0	"^FS: GEN: Digital Breath  ""NRL"" 2013"
    
    25	00:05.00	JA0775G0	"^FS: GEN: Digital Breath  ""NRL2"" 2013 "
    
    26	00:05.00	JA0776G0	"^FS: GEN: Digital Breath  ""RUN"" 2013"
    
    27	00:05.00	JA0777G0	"^FS: GEN: Digital Breath  ""SRUN"" 2013 "
    
    28	00:05.00	JA0778G0	"^FS: GEN: Digital Breath  ""WEB"" 2013 "
    
    29	00:05.00	JA0779G0	"^FS: GEN: Digital Breath  ""WEB"" 2013"
    
    30	00:05.00	JA0781G0	"^FS: GEN: Digital Breath  ""Foxtel Go 1"" 2013"
    
    31	00:05.00	JA0782G0	"^FS: GEN: Digital Breath  ""Foxtel Go2"" 2013 "
    
    32	00:45.00	JA0780G0	"^FS: GEN: FoxSports Relaunch ""Talent"" 2013"
    
    33	01:00.00	JA0574G1	"FS: AFL Who Ever You Love Image 2013 60"" V2"
    
    34	01:00.00	JA0582G1	"FS: AFL: Launch Image Games 60"" V2"
    
    35	01:00.00	JA0587G1	"FS: AFL: Image 2013 ""Great Moments"" 60"" V2"
    
    36	01:00.00	JA0681G0	"FS: AFL: Fox Footy Image ""TALENT"" 2013 60"""
    
    37	01:00.00	JA0786G0	"FS: AFL: Friday Night Ritual 60"""
    
    38	00:30.00	JA0575G1	"FS: AFL Who Ever You Love Image 2013 30"" V2"
    
    39	00:30.00	JA0586G1	"FS: AFL: Launch Image Games 30"" V2"
    
    40	00:30.00	JA0588G1	"FS: AFL: Image 2013 ""Great Moments"" 30"" V2"
    
    41	00:30.00	JA0622T0	"FS: AFL: On The Couch Launch TON 2030 (18/03) 30"""
    
    42	00:30.00	JA0652T0	"FS: AFL: Open Mike ""Launch"" MON 2130 (18/03) 30"""
    
    43	00:30.00	JA0682G0	"FS: AFL: Fox Footy Image ""TALENT"" 2013 30"""
    
    44	00:30.00	JA0699G1	"FS: AFL Who Ever You Love V2 Image 2013 30"" V2"
    
    45	00:30.00	JA0704D0	"FS: AFL: 2012 GF Recall Syd v Haw SUN 2030 (24/03) 30"""
    
    46	00:30.00	JA0787G0	"FS: AFL: Friday Night Ritual 30"""
    
    47	00:30.00	JA0788G0	"FS: AFL: Friday Night Ritual ""Ricciuto"" 30"""
    
    48	00:30.00	JA0820C0	"FS: FTB: Socceroos v Oman CSN (26/3) 30"""
    
    49	00:15.00	JA0576G1	"FS: AFL Who Ever You Love Image V1 2013 15"" V2"
    
    50	00:15.00	JA0577G1	"FS: AFL Who Ever You Love Image V2 2013 15"" V2"
    
    51	00:15.00	JA0619G1	"FS: AFL Who Ever You Love Image V3 2013 15"" V2"
    
    52	00:15.00	JA0620G1	"FS: AFL Who Ever You Love Image V4 2013 15"" V2"
    
    53	00:15.00	JA0621G2	"FS: AFL Who Ever You Love Image V5 2013 15"" V3"
    
    54	00:15.00	JA0705D0	"FS: AFL: 2012 GF Recall Syd v Haw ""GOODES"" SUN 2030 (24/03) 15"" "
    
    55	00:15.00	JA0706D0	"FS: AFL: 2012 GF Recall Syd v Haw ""MALCESKI"" SUN 2030 (24/03) 15"""
    
    56	00:15.00	JA0707G1	"FS: AFL Who Ever You Love Image V6 ROO 2013 15"" V2"
    
    57	00:15.00	JA0789G0	"FS: AFL: Friday Night Ritual 15"""
    
    58	00:20.00	JA0790G0	"FS: AFL: Friday Night Ritual ""Healy"" 20"""
    
    59	00:10.00	JA0821C0	"FS: FTB: Socceroos v Oman CSN (26/3) 10"""
    

    Groovy is the new Perl for me, I am not writing any linux scripts with Perl ever again.