Groovy - Get first elements in multi-dimensional array - groovy

I have a groovy list of lists i.e.
list = [[2, 0, 1], [1, 5, 2], [1, 0, 3]]
I would like to get a subset of just the first elements of each array
sublist = [2, 1, 1]
I know I can loop through the and just get the first element and add, but I am trying to avoid this since I have a huge array of values. I'm trying to avoid this solution
def sublist = []
list.each {
sublist.add(it[0])
}
Thanks.

A more readable version:
list*.first()

You could try:
list.collect { it[0] }
Although that still involves iteration (although somewhat hidden). However, it's likely that any solution is going to involve iteration somewhere down the line, whether it be written by you or the library/API method you call.

If you're worried about copying the data, a better approach might be to create a custom iterator, rather than copying the data into another list. This is a great approach if you only need to traverse through the sublist once. Also, if you don't traverse to the end of the sublist, you haven't wasted any effort on the elements you never processed. For example:
bigList = [[2, 0, 1], [1, 5, 2], [1, 0, 3]]
bigListIter = bigList.iterator()
firstOnlyIter = [
hasNext: { -> bigListIter.hasNext() },
next: { -> bigListIter.next().first() }
] as Iterator
for (it in firstOnlyIter) {
println it
}
You can always turn the iterator back into a list with Iterator.toList().

Related

Is there a way to sort an unsorted list with some repeated elements?

I am trying to sort an unsorted list [4, 5, 9, 9, 0, 1, 8]
The list has two repeated elements. I have tried to approach the question by having a loop that goes through each element comparing each element with the next in the list and then placing the smaller element at the start of the list.
def sort(ls:
ls[x]
x = [4, 5, 9, 9, 0, 1, 8]
while len(x) > 0:
for i in the range(0, len(x)):
lowest = x[i]
ls.append(lowest)
Please, could someone explain where I am going wrong and how the code should work?
It may be that I have incorrectly thought about the problem and my reasoning for how the code should work is not right
I do not know, if this is exactly what you are looking for but try: sorted(ListObject).
sorted() returns the elements of the list from the smallest to the biggest. If one element is repeated, the repeated element is right after the original element. Hope that helped.
Yes, you can try x.sort() or sorted(x). Check this out https://www.programiz.com/python-programming/methods/built-in/sorted. Also, in your program I don't see you making any comparisons, for example, if x[i] <= x[i+1] then ...
This block of code is just gonna append all the elements in the same order, till n*n times.
Also check this https://en.wikipedia.org/wiki/Insertion_sort
For a built-in Python function to sort, let y be your original list, you can use either sorted(y) or y.sort().Keep in mind that sorted(y) will return a new list so you would need to assign it to a variable such as x=sorted(y); whereas if you use x.sort() it will mutate the original list in-place, so you would just call it as is.
If you're looking to actually implement a sorting function, you can try Merge Sort or Quick Sort which run in O (n log n) in which will handle elements with the same value. You can check this out if you want -> https://www.geeksforgeeks.org/python-program-for-merge-sort/ . For an easier to understand sorting algorithm, Insertion or Bubble sort also handle duplicate as well but have a longer runtime O (n^2) -> https://www.geeksforgeeks.org/python-program-for-bubble-sort/ .
But yea, I agree with Nameet, what you've currently posted looks like it would just append in the same order.
Try one of the above suggestions and hopefully this helps point you in the right direction to if you're looking for a built-in function or to implement a sort, which can be done in multiple ways with different adv and disadv to each one. Hope this helps and good luck!
There are several popular ways for sorting. take bubble sort as an example,
def bubbleSort(array):
x = len(array)
while(x > 1): # the code below make sense only there are at least 2 elements in the list
for i in range(x-1): # maximum of i is x-2, the last element in arr is arr[x-1]
if array[i] > array[i+1]:
array[i], array[i+1] = array[i+1], array[i]
x -= 1
return array
x = [4, 5, 9, 9, 0, 1, 8]
bubbleSort(x)
your code has the same logic as below
def sorts(x):
ls = []
while len(x) > 0:
lowest = min(x)
ls.append(lowest)
x.remove(lowest)
return ls
x = [4, 5, 9, 9, 0, 1, 8]
sorts(x)
#output is [0, 1, 4, 5, 8, 9, 9]

python 3 vector subtraction with out numpy

I'm fairly new to coding in the python3 language. I'm trying to construct a function that takes two vectors and subtracts them. Any help would be great. Thank you in advance.
Write a function vecSubtract(vector01, vector02) which takes in two vectors as arguments, and returns the vector which is equal to vector01-vector02.
def vecSubtract(vector01,vector02):
for i in range(min(len(vector01), len(vector02))):
result = [vector01[i]-vector02[i] ]
return result
vector01 = [3, 3, 3]
vector02 = [4, 4, 4]
print(vecSubtract(vector01,vector02))
While you are looping over the vectors (lists actually), you are overwriting your result variable every time.
You probably want to use a list comprehension instead.
def vecSubtract(vector01, vector02):
result = [vector01[i] - vector02[i] for i in range(min(len(vector01), len(vector02)))]
return result
vector01 = [3, 3, 3]
vector02 = [4, 4, 4]
print(vecSubtract(vector01,vector02))
If you really want to use a for loop, you should use result.append() instead of overwriting the variable every time.
Also, it is probably not right to allow subtraction of vectors of different lengths by ignoring the surplus elements in the longer vector. Instead you should probably test that the two vectors are the same length and have the script throw an error if they are not.

Underscore GroupBy Sort

I have a question regarding programming in function style.
I use underscore.js library.
Let's consider some use-case. I have an array of some labels with repetitions I need to count how many occurrences of each label is in array and sort it according to the number of occurrences.
For counting, how many labels I can use countBy
_.countBy([1, 2, 3, 4, 5], function(num) {
return num % 2 == 0 ? 'even': 'odd';
});
=> {odd: 3, even: 2}
But here, as result I have a hash, which doesn't have meaning for order, so there is no sort. So here, I need to convert the hash to array then to sort it and convert backward to hash.
I am pretty sure there is an elegant way to do so, however I am not aware of it.
I would appreciate any help.
sort it and convert backward to hash.
No, that would loose the order again.
You could use
var occurences = _.countBy([1, 2, 3, 4, 5], function(num) {
return num % 2 == 0 ? 'even': 'odd';
});
// {odd: 3, even: 2}
var order = _.sortBy(_.keys(occurences), function(k){return occurences[k];})
// ["even", "odd"]
or maybe just
_.sortBy(_.pairs(occurences), 1)
// [["even", 2], ["odd", 3]]

How to get all elements from a list without the last element?

The following Groovy code
lines = ['0','1','2','3','4','5']
println lines[1..lines.size()-1]
println lines[1..-1]
println lines[1..<lines.size()-1]
println lines[1..<-1]
println lines[1..<-2]
println lines[1..-2]
produces this output:
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
[1, 2, 3, 4]
[1, 0]
[1, 2, 3, 4, 5]
[1, 2, 3, 4]
Since -1 is the index of the last element in the list, the first two make sense (ranges in Groovy include the end element instead of omitting it as everywhere else in Java :-( )
Line #3 is the desired output (list without first and last element).
I'm worried about the output #4: Why do I get [1, 0] for 1..-1?
Also [1, 2, 3, 4, 5] for the range 1..<-2 seems wrong.
Why does that happen?
The best way to take all elements but the last one, in my opinion, is to use the take method:
def list = ['a', 'b', 'c']
assert list.take(list.size() - 1) == ['a', 'b']
It behaves properly in the corner case where size == 1:
def list = ['one']
assert list.take(list.size() - 1) == []
Though I'd prefer it to throw an exception in the case size == 0, but the behavior is not that bad:
def list = []
assert list.take(list.size() - 1) == []
You can also use list[0..<list.size()-1] (your third example) and it will behave the same except for the empty list, in which case it will throw an ArrayIndexOutOfBoundsException, but i think is not as readable as the take counterpart.
Another acceptable solution is using list[0..-2] (your last example), which i think looks much more elegant, but unfortunately breaks when size == 1 with an ArrayIndexOutOfBoundsException.
In your examples (i'll assume that you meant to use 0 as the starting index instead of 1 if you wanted to include all elements but the last one):
lines[0..lines.size()-1] is equivalent to lines[0..-1] because the getAt(Range) method of lists will treat ranges with negative indexes the same way asgetAt(Integer) does, i.e. as accessing the (list.size() + negativeIndex)'th element of the list. Therefore list[0..-1] is the same as saying "from first element to last" and it's the same as copying the list; and list[-1..0] is the same as "from last to first" and it's equivalent to list.reverse() :)
The problem with the other non-inclusive range example is that the non-inclusive ranges are being evaluated before the list access and they evaluate to an incorrect inclusive range. For example, 0..<-2 evaluates to 0..-1, and that's why it's returning all the elements. 0..<-1 evaluates to 0..0 and it returns only the first element.
Notice that the empty range is a special case. It's denoted as 0..<0 and it doesn't have an inclusive equivalent (so Groovy won't do any magic conversion here). And that's why list[0..<list.size()-1] works when size == 1 (the range evaluates to the empty range) while list[0..-2] doesn't :)
Maybe this has changed since epideman wrote his answer, but you can get the whole list without the last element with 0..<-1:
assert ["foo"][0..<-1] == []
assert ["foo", "bar"][0..<-1] == ["foo"]
assert ["foo", "bar", "baz"][0..<-1] == ["foo", "bar"]
// blows up if empty, here take is better
assert [][0..<-1] == [] // BOOM
// if you want null safe, use take
assert [].take(-1) == []
This is with groovy 2.2.1.
Since Groovy 2.4 you can use the init() method:
lines = ['0','1','2','3','4','5']
assert lines.init() == ['0','1','2','3','4']

How to Add item to start of list using Groovy?

How can I use Groovy to add an item to the beginning of a list?
list.add(0, myObject);
You can also read this for some other valuable examples:
http://groovy.codehaus.org/JN1015-Collections
Another option would be using the spread operator * which expands a list into its elements:
def list = [2, 3]
def element = 1
assert [element, *list] == [1, 2, 3]
Another alternative would be to put the element into a list and concatenate the two lists:
assert [element] + list == [1, 2, 3]​
Caution!
From Groovy 2.5:
list.push( myObject )
Prior to Groovy 2.5 list.push appends ... but from 2.5/2.6 (not yet Beta) it will (it seems) prepend, "to align with Java"... indeed, java.util.Stack.push has always prepended.
In fact this push method does not belong to List, but to GDK 2.5 DefaultGroovyMethods, signature <T> public static boolean push(List<T> self, T value). However, because of Groovy syntax magic we shall write as above: list.push( myObject ).
def list = [4, 3, 2, 1, 0]
list.plus(0, 5)
assert list == [5, 4, 3, 2, 1, 0]
You can find more examples at this link

Resources