The following java code exists but I'm trying to convert it to groovy. Should I simply keep it as is w/ the System.arraycopy or does groovy have a nicer way to combine arrays like this?
byte[] combineArrays(foo, bar, start) {
def tmp = new byte[foo.length + bar.length]
System.arraycopy(foo, 0, tmp, 0, start)
System.arraycopy(bar, 0, tmp, start, bar.length)
System.arraycopy(foo, start, tmp, bar.length + start, foo.length - start)
tmp
}
Thank you
def a = [1, 2, 3]
def b = [4, 5, 6]
assert a.plus(b) == [1, 2, 3, 4, 5, 6]
assert a + b == [1, 2, 3, 4, 5, 6]
If you want to use an array:
def abc = [1,2,3,4] as Integer[] //Array
def abcList = abc as List
def xyz = [5,6,7,8] as Integer[] //Array
def xyzList = xyz as List
def combined = (abcList << xyzList).flatten()
Using Lists:
def abc = [1,2,3,4]
def xyz = [5,6,7,8]
def combined = (abc << xyz).flatten()
def a = [1, 2, 3]
def b = [4, 5, 6]
a.addAll(b)
println a
>> [1, 2, 3, 4, 5, 6]
The trick is the flatten() method, that combined nested arrays into one:
def a = [1, 2, 3]
def b = [4, 5, 6]
def combined = [a, b].flatten()
assert combined == [1, 2, 3, 4, 5, 6]
println(combined)
To remove null values you can use findAll() like this:
def a = null
def b = [4, 5, 6]
def combined = [a, b].flatten().findAll{it}
assert combined == [4, 5, 6]
println(combined)
I'd go with
byte[] combineArrays(foo, bar, int start) {
[*foo[0..<start], *bar, *foo[start..<foo.size()]]
}
It could be done like this:
def newCombine(foo,bar,start) {
([].add + foo[0..<start]+bar+foo[start..<foo.size()]).flatten()
}
It works for all kinds of arrays (byte[]) or lists
All the solutions above fails if an array is undefined:
def a = [1,2]
def b
assert a+b == [1, 2, null]
which is probably not what you want.
Either test if the array exists before adding:
def a = [1,2,3,4]
def b // null array
def c = [0,4,null,6]
def abc = []
[a,b,c].each{ if (it) abc += it }
assert abc == [1, 2, 3, 4, 0, 4, null, 6]
,or add all and then filter the output:
(a+b+c).findAll{ it != null }
(assuming here that null isn't a valid value in the original arrays, which implies that the first solution is a lot better, even if it may not look Groovy enough.)
Related
I have the following code for checking if the values in a given list are all equal:
def myList = [1, 2, 3, 4]
def myList2 = [1, 1, 1, 1]
def list1EqualVals = myList.collect{ it == myList[0] }.inject(true){it, tmp -> it == tmp}
def list2EqualVals = myList2.collect{ it == myList2[0] }.inject(true){it, tmp -> it == tmp}
println "List 1 has equal values: $list1EqualVals"
println "List 2 has equal values: $list2EqualVals"
which works and it prints:
List 1 has equal values: false
List 2 has equal values: true
but is there a better way of doing this? maybe some method I miss? like list.containsAllEqualValues() or similar
You can convert the List into Set:
A collection that contains no duplicate elements.
and check its size(). If a resulting Set has only one element it means all the values in the List are the same.
def myList = [1, 2, 3, 4]
def myList2 = [1, 1, 1, 1]
def list1EqualVals = myList.toSet().size() == 1
def list2EqualVals = myList2.toSet().size() == 1
println "List 1 has equal values: $list1EqualVals"
println "List 2 has equal values: $list2EqualVals"
Alternatively, you can also use the native Groovy toUnique() method to achieve the same:
def myList = [1, 2, 3, 4]
def myList2 = [1, 1, 1, 1]
def list1EqualVals = myList.toUnique().size() == 1
def list2EqualVals = myList2.toUnique().size() == 1
println "List 1 has equal values: $list1EqualVals"
println "List 2 has equal values: $list2EqualVals"
I want to check for a certain condition list and then print it
suppose i want to check items of a in b
I want to check for values of list "a" in list "b" so i used this code
a=[1,2]
b=[1,2,3,4,5,6,7,8,9,]
c=[]
for i in a:
for j in b:
if i!=j:
c.append(j)
but i am getting infinite loop when i run this code code please help me.
It is unclear what behavior you would like to implement, but I guess you want to filter out elements in b that appear in a. If so, you can do this:
a = [1, 2]
b = [1, 2, 3, 4, 5, 6, 7, 8, 9]
c = []
for i in b:
if not i in a:
c.append(i)
print(c)
The result:
[3, 4, 5, 6, 7, 8, 9]
**If you want to recover
identical elements in each list then try this code:**
c = []
def list_contains(a, b):
for x in a:
for y in b:
if x == y:
c.append(x)
continue
return c
a = [1, 2]
b = [1, 2, 3, 4, 5, 6, 7, 8, 9, ]
print(list_contains(a, b))
Let's use some list comprehension!
I'll rename your lists:
list_a = [1, 2]
list_b = [1, 2, 3, 4, 5, 6, 7, 8, 9]
So you want a list of everything in list_b...
result = [elem for elem in list_b] # (this just copies the list)
...where the element is also in list_a:
result = [elem for elem in list_b if elem in list_a]
...where the element is not in list_a:
result = [elem for elem in list_b if elem not in list_a]
Alternatively, make a function and use filter:
def keep_b_if(b_elem):
return b_elem in list_a
# or
return b_elem not in list_a
result = filter(keep_b_if, list_b)
Also, if a is just a collection of values to preserve/lose from b, it can be a set instead of a list:
forbidden = {1, 2}
...
if elem not in forbidden:
...
Trying to solve freecodecamp's symmetric difference challenge (https://www.freecodecamp.org/learn/coding-interview-prep/algorithms/find-the-symmetric-difference), I wrote the following function:
def symdiff(*args):
dump = [x for x in args[0] if x in args[1]]
result = [x for x in args[0] + args[1] if x not in dump]
if len(args) == 2:
return result
else:
symdiff(result, *args[2:])
var = symdiff([1, 2, 3], [3, 2, 0], [7, 2, 6])
print(var)
The value of var turns out to be None. Why is that? I expected it to be [7, 2, 6, 1, 0]. I entered a print(result) just before return result and it printed the correct answer.
In your else block, you need to return symdiff.
def symdiff(*args):
dump = [x for x in args[0] if x in args[1]]
result = [x for x in args[0] + args[1] if x not in dump]
if len(args) == 2:
return result
else:
return symdiff(result, *args[2:])
var = symdiff([1, 2, 3], [3, 2, 0], [7, 2, 6])
print(var)
The above code should work.
Let us say we have a list of integers:
list = [6, 4, 1, 4, 4, 4, 4, 4, 2, 1]
I now wrote a function which returns another list with all the integers from the list above without repeats.
def no_repeats(s):
new_list = []
for number in s:
if new_list.count(number) < 1:
new_list.append(number)
return(new_list)
The new_list returns [6, 4, 1, 2] which is good! My question is how I would now write two similar functions:
A function clean(s) which does not return a new list like the function above, but changes the original list by deleting all the numbers that repeat. Thus, the result has to be the same and the function must not include "return" or create a new list. It must only clean the original list.
A function double(s) which, again, changes the original list (does not return a new list!) but this time, by doubling every number in the original list. Thus, double(list) should change the original list above to:
[6, 6, 4, 4, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 1, 1]
Thank you for all the help!
Removing duplicates inplace without preserving the order:
def no_repeats(L):
L[:] = set(L)
There are several variations possible (preserve order, support non-hashable items, support item that do not define total ordering) e.g., to preserve order:
from collections import OrderedDict
def no_repeats(L):
L[:] = OrderedDict.fromkeys(L)
To double each element's value inplace:
def double(L):
for i in range(len(L)):
L[i] *= 2
To duplicate each element:
def duplicate_elements(L):
L[:] = [x for x in L for _ in range(2)]
>>> def clean(s):
... s[:] = [s[i] for i in range(len(s)) if s[i] not in s[:i]]
...
>>> st = [1, 2, 3, 2, 1]
>>> clean(st)
>>> st
[1, 2, 3]
>>> def double(s):
... s[:] = [s[i//3] for i in range(3*len(s)) if i % 3]
...
>>> st = [1, 2, 3, 2, 1]
>>> double(st)
>>> st
[1, 1, 2, 2, 3, 3, 2, 2, 1, 1]
neither is particularly efficient nor pythonic, yet do address the OP question
def double(s):
... s[:] = [s[i//2] for i in range(2*len(s))]
will also do the trick, with a little less obsfucation
Let's say I've got a list of numbers:
def list = [1, 2, 3, 4, 5]
I want to separate it into two groups - odd and even numbers.
I am doing it like this:
def map = list.groupBy { it % 2 == 1 }
The resulting map looks like this
[true:[1, 3, 5], false:[2, 4, 6]]
But how to set my custom key for odd and even values instead of having true and false?
Here you are:
def list = [1, 2, 3, 4, 5, 6, ]
def map = list.groupBy { it % 2 ? 'odd' : 'even' }