How do i replace only required field in Groovy - groovy

I have two lists :
a = [1,2,3]
b = ["?",1,2,"?",4,"?"]
In the second list, I need to replace the first "?" with first element of a(i.e a[0]) and second "?" with a[1] and so on(provided that the number of "?" = size of a) and the result as modified b.
How I can do this groovy-er way?
Thanks in advance.

Some simple solutions:
This returns the result in a new list (you can assign this result to the b variable)
def i = 0
b.collect { it == "?" ? a[i++] : it }
This modifies the list referenced by b
a.each { b[b.indexOf("?")] = it }

Related

Assign matched item in list to a variable

The motive is to check if any of items in a list are contained in another list, and in case there is a match, assign it to a variable in a 'pythonic' fashion
if any('a','b','c') in ['b','x','y','z']:
#now i want to assign the matched 'b' to a variable concisely.
#In case of multiple matches , any match/ first match may be assigned
I want to avoid this :
lst = ['b','x','y','z']
if 'a' in lst:
var = 'a'
elif 'b' in lst"
var = 'b'
# and so on
You can use a function that returns either the first matched element or None in case no matched elements are found:
li_1 = ['a','b','c']
li_2 = ['b','x','y','z']
def find(li_1, li_2):
for e in li_1:
if e in li_2:
return e
print(find(li_1, li_2))
# b
print(find(['a'], ['b']))
# None
Note that this is an O(n^2) solution. If the items are hashable you can get an O(1) solution using sets intersection (and as a bonus you will get all matched elements):
li_1 = ['a','b','c']
li_2 = ['b','x','y','z']
s1 = set(li_1)
s2 = set(li_2)
print(s1.intersection(s2)) # or print(s1 & s2)
# {'b'}

SML - Find element in a list and substitute it

I'm trying to build a function which takes as input two list of type
(string*string) list
and returns one list of the same type. The first list is like a "lookup" list in which the second element is the element to search and the first element is the element to use for the substitution. The aim of the function is to find which element in the second list is equal to which element of the first list. In case of matching the element of the second list will be substitute with the correspondent element of the tuple in the first element. Below an example:
fun check([("0","s0"),("1","s0l0s1"),("2","s1"),("3","s1l1s0")],[("s0","s0l0s1"),("s0l0s1","s1"),("s1","s1l1s0"),("s1l1s0","s0")]);
With these inputs the function should return:
val it = [("0","1"),("1","2"),("2","3"),("3","0")]
Since "s0" corresponds to "0", "s0l0s1" corresponds to "1", "s1" corresponds to "2" and "s1l1s0" corresponds to "3".
I've done two functions so far:
fun check1((l1 as (x1,y1))::nil,(l2 as (x2,y2))::nil) = if x2 = y1 then [(x1,y2)] else nil
|check1((l1 as (x1,y1))::rest1,(l2 as (x2,y2))::rest2) =
if x2 = y1 then (x1,y2)::check1(rest1,rest2)
else check1(rest1,l2::rest2)
fun check2((l1 as (x1,y1))::nil,(l2 as (x2,y2))::nil) = if y2 = y1 then [(x2,x1)] else nil
|check2((l1 as (x1,y1))::rest1,(l2 as (x2,y2))::rest2) =
if y2 = y1 then (x2,x1)::check2(rest1,rest2)
else check2(rest1,l2::rest2)
The first one checks the element of the first tuple of the second list and the second function checks the element of the second tuple. But they don't work properly. Someone can help me in understanding where is the mistake?
Thanks a lot!
You're making this way too complicated.
This first function looks up a string in the first list:
fun lookup ((a,b)::xs) v = if v = b then a else lookup xs v
| lookup nil v = v;
And this one just runs recursively on both elements in the second list:
fun check (xs,((a,b)::ys)) = (lookup xs a, lookup xs b)::check(xs,ys)
| check (xs,nil) = nil;

Get any consecutive sequence containing the given number of elements that matches a fixed condition from a list C#

I have a list defined as below inside a method
List<string> testList = new List<string>() {"A","A","B","A","A","A","B"};
Here my condition will be fixed say where the element matches "A". Based on upon my input, for instance 2, logic should identify two consecutive A's in the list and return them. In the above list it should return first and second elements. If my input is 3 it should return fourth,fifth and sixth elements where three A's are consecutive. If it is 4 it should not return anything. Is there a simple way of implementing this in C#
This is one way to do what you want:
List<string> testList = new List<string>() {"A","A","B","A","A","A","B"};
string inputText = <your input text>;
int inputCount = <your input count>;
var zipped = testList.Zip(Enumerable.Range(0,testList.Count-1), (txt,idx) => new {txt,idx});
var result = zipped
.Where(combined => combined.idx <= testList.Count-inputCount)
.Where(combined => combined.txt == inputText
&& testList.GetRange(combined.idx, inputCount).All(z => z == inputText));
We zip with the ordered range [0..list count - 1] to provide indexes for your elements. Then we check if current element in the collection equals the input text, and if the first n elements starting from current one all equal input text, where n is the input count.
We can then use a foreach loop to iterate through result like so:
foreach(var r in result)
{
testList.GetRange(r.idx,inputCount).ForEach(x => Console.WriteLine(x));
}
For each pattern that is found, we use GetRange to get the corresponding values.
Note that we are creating another IEnumerable object when we call Zip, and also calling GetRange within the Where clause, so I don't think this method is very efficient. Nevertheless, it will solve the issue.

Good Way to Filter Object in a List Which A property Equal B property in Two Object

I have list of Objects(Name A), A have property B and C. I need to find the object in the list which B property equal with another object's C property. For Example:
def objectList = [A1,A2,A3,A4,A5,A6,A7,A8];
if A1.B == A2.C then return A1,A2;
Any good way to do that?
You can use the findAll method for this:
def list = []
def matching = list.findAll { A a ->
a.B == a.C
}
Update
You can get all the pairs of matching objects this way:
def matching = []
list.unique { A a1, A a2 ->
if (a1.B == a2.C || a1.C == a2.B) {
matching << a1 << a2
}
return 1
}
This is kind of a hacky solution since it does not use the unique method as intended.
Not sure whether you want your result flattened or not, anyway here's a solution returning a list of tuples:
def result = list.inject([]) {acc,a1->
list.each {a2->
if (!a1.is(a2) && a1.b == a2.c) {
acc << [a1,a2]
}
}
acc
}

groovy - is there any implicit variable to get access to item index in "each" method

Is there any way to remove variable "i" in the following example and still get access to index of item that being printed ?
def i = 0;
"one two three".split().each {
println ("item [ ${i++} ] = ${it}");
}
=============== EDIT ================
I found that one possible solution is to use "eachWithIndex" method:
"one two three".split().eachWithIndex {it, i
println ("item [ ${i} ] = ${it}");
}
Please do let me know if there are other solutions.
you can use eachWithIndex()
"one two three four".split().eachWithIndex() { entry, index ->
println "${index} : ${entry}" }
this will result in
0 : one
1 : two
2 : three
3 : four
Not sure what 'other solutions' you are looking for... The only other thing you can do that I can think of (with Groovy 1.8.6), is something like:
"one two three".split().with { words ->
[words,0..<words.size()].transpose().collect { word, index ->
word * index
}
}
As you can see, this allows you to use collect with an index as well (as there is no collectWithIndex method).
Another approach, if you want to use the index of the collection on other methods than each is to define an enumerate method that returns pairs [index, element], analog to Python's enumerate:
Iterable.metaClass.enumerate = { start = 0 ->
def index = start
delegate.collect { [index++, it] }
}
So, for example:
assert 'un dos tres'.tokenize().enumerate() == [[0,'un'], [1,'dos'], [2,'tres']]
(notice that i'm using tokenize instead of split because the former returns an Iterable, while the later returns a String[])
And we can use this new collection with each, as you wanted:
'one two three'.tokenize().enumerate().each { index, word ->
println "$index: $word"
}
Or we can use it with other iteration methods :D
def repetitions = 'one two three'.tokenize().enumerate(1).collect { n, word ->
([word] * n).join(' ')
}
assert repetitions == ['one', 'two two', 'three three three']
Note: Another way of defining the enumerate method, following tim_yates' more functional approach is:
Iterable.metaClass.enumerate = { start = 0 ->
def end = start + delegate.size() - 1
[start..end, delegate].transpose()
}

Resources