0

Referring to this question: How to subtract dates from each other

In Groovy, I've got a script that spits out the 5 largest values from a text file collection. How can I know what the indices of those values are?

Community
  • 1
  • 1
blaughli
  • 517
  • 5
  • 11
  • 27

2 Answers2

0

If you have a list of things ie:

def list = [ 'c', 'a', 'b' ]

One way of knowing the original index would be to use transpose() to join this list to a counter, then sort the new list, then you will have a sorted list with the original index as the secondary element

ie:

[list,0..<list.size()].transpose().sort { it[0] }.each { item, index ->
  println "$item (was at position $index)"
}

To break that down;

[list,0..<list.size()]

gives us (effectively) a new list [ [ 'c', 'a', 'b' ], [ 0, 1, 2 ] ]

calling transpose() on this gives us: [ [ 'c', 0 ], [ 'a', 1 ], [ 'b', 2 ] ]

We then sort the list based on the first item in each element (the letters from our original list) with sort { it[0] }

And then iterate through each, printing out our now sorted item, and its original index location

tim_yates
  • 167,322
  • 27
  • 342
  • 338
  • Thank you Tim, I greatly appreciate your explanation. You are helping me learn, I can't tell you how great it is to get the breakdown. I won't be just copying and pasting (after TRYING to figure out the code); you are imparting an understanding and setting me up to use these concepts in the future. Teach a man to fish... – blaughli Nov 11 '11 at 00:02
  • Great answer as always :). However, I think the transpose trick might be a little too clever. A `collect` with a counter can do the magic too: `def i = 0; list.collect { [it, i++] }` and maybe it is simpler to understand. An `inject` can also do it and not require an extra statement, but I think it's not as pretty. It is a shame that `collect` does not accept a closure with element and index ([yet](https://jira.codehaus.org/browse/GROOVY-3797)) or that there is no Python-like `enumerate`. – epidemian Nov 11 '11 at 01:28
  • @epidemian Hi! I completely agree that using an external counter variable is easier to read, but since I've started doing more functional programming, I've tried to stay away from defining explicit variables as much as possible. It might just be that a part of my programming brain has been broken by learning Clojure though ;-) – tim_yates Nov 11 '11 at 08:53
  • @tim_yates Yeah, functional programming can have, ironically, that side-efect in our brains hehe. I like it too. Maybe if I were to go with this approach I would add an `enumerate` method to the `List` to get a list of (index, value) pairs like the [Python's equivalent](http://docs.python.org/library/functions.html#enumerate). Cheers. – epidemian Nov 11 '11 at 17:49
0

If the values are unique, you might just use the indexof method over the original list. For example, if you have the list:

def list = [4, 8, 0, 2, 9, 5, 7, 3, 6, 1]

And you know how to get the 5 largest values:

def maxVals = list.sort(false, {-it}).take 5 // This list will be [9, 8, 7, 6, 5]

You can then do:

def indexes = maxVals.collect { list.indexOf it }
println indexes

And it will print:

[4, 1, 6, 8, 5]
epidemian
  • 18,817
  • 3
  • 62
  • 71
  • can you describe what your 2nd line of code is doing please? `def maxVals...` – blaughli Nov 15 '11 at 18:47
  • @blaughli Sure! I'm using the method [`sort(boolean mutate, Closure closure)`](http://groovy.codehaus.org/groovy-jdk/java/util/Collection.html#sort%28boolean,%20groovy.lang.Closure%29). Passing `false` as the first parameter prevents the sort method from modifying the original list; it returns a new sorted list instead. The second parameter is a closure that returns the value to use for comparison in the sort method. In this case, passing the closure `{-it}` will sort the list in descending order. The whole line is equivalent to `def maxVals = list.clone().sort().reverse().take(5)` – epidemian Nov 15 '11 at 19:00
  • I think the most readable form may be `def maxVals = list.sort(false).reverse().take(5)`. – epidemian Nov 15 '11 at 19:07
  • Beautiful, thanks so much! Did you guys get good in school? Or just with practice? – blaughli Nov 15 '11 at 19:36
  • @blaughli That's kinda off-topic, and there sure will be good articles on how to get better at programming if you google them. I can only talk about my experience I think. A few years in university helped me a lot to get some discipline of getting things done and learning new stuff. But I think what makes the difference is to always be looking for better ways of doing things (e.g. asking or looking for answers in StackOverflow =D); both at work or doing homework projects for the university, it's usually not required that you write good code, so it's up to you to care about that or not. Cheers! – epidemian Nov 16 '11 at 12:48