Groovy map : get the count of value that a key holds - groovy

I have a map,
def map= [name:[Vin], email:[vin#gmail.com], phone:[9988888888], jobTitle:[SE]]
i want get the total number of values that a key holds
for ex,
key name can have many values like [name:[Vin,Hus,Rock] how to do it programatically?
def count = map.name.size() //gives wrong answer

You can use the following code to get a list of size for all key.
def map= [name:['Vin',''], email:['vin#gmail.com'], phone:['9988888888'], jobTitle:['SE']]
map.collect{it.value.size()}
Output:
[2, 1, 1, 1]
I think map.name.size() should work fine too in groovy.

def map= [name :['Vin', 'abc', 'xyz'],
email:['vin#gmail.com'],
phone:[9988888888],
jobTitle:['SE']]
//Spread operator to get size of each value
assert map.values()*.size == [3, 1, 1, 1]
//Implicit spread
assert map.values().size == [3, 1, 1, 1]
//use size() to get the size of the values collection
assert map.values().size() == 4
//Values
assert map.values() as List == [['Vin', 'abc', 'xyz'],
['vin#gmail.com'], [9988888888], ['SE']]

Related

How to get all keys and values in list of Nested dictionaries?

di = [{ "k": [1, 3, 5], "k1": { "k10" : 4, "k11": [4, 7, 9], "k12" : { "k120" : { "k121" : "v121" }}, "k14" : 6}}, {"k22": { "k221" : "v122"}}]
key_list = list()
val_list = list()
for i in di:
key_list.extend(i.keys())
val_list.extend(i.values())
for i in val_list:
if "dict" in str(type(i)):
key_list.extend(i.keys())
val_list.remove(i)
val_list.extend(i.values())
for i in val_list:
if "dict" in str(type(i)):
key_list.extend(i.keys())
val_list.remove(i)
val_list.extend(i.values())
print("Key list: ",key_list)
print("Vlaue list: ", val_list)
"""This is giving my answer but i need a optimised way and also for N nested dictionary how to get all keys and values, I need get all keys in a list and all values in a list."""
About optimization: If there is a reason of existing hierarchy there is not "optimised way" to disrespect the hierarchy, otherwise a real optimization needs to include a change not to construct the hierarchy that would be disrespected later.
I wrote the following, is not optimized but decently efficient and concise, it does something in the direction of what you imprecisely asked: (I let you refine what you intend to be returned, I noticed that you silently excluded to return those value whose type is dictionary, I didn't make such discrimination). To help to understand the flexibility of the code I made some examples as cases controlled by the behavioral variable bkv, this behavioral variable can be squeezed when you know what you want to obtain.
dictype=type({})
listype=type([])
def through(ref,bkv):
""" bkv in binary 01=1 yield key
10=2 yield value
11=3 yield (key,value) """
if type(ref)==listype:
for x in ref:
yield from through(x,bkv)
elif type(ref)==dictype:
for kv in ref.items():
if bkv==1:
yield kv[0]
elif bkv==2:
yield kv[1]
elif bkv==3:
yield kv
else:
throw(TypeError, "Not implemented")
yield from through(kv[1],bkv)
di = [
{ "k": [1, 3, 5],
"k1": { "k10" : 4,
"k11": [4, 7, 9],
"k12" : { "k120" : { "k121" : "v121" }},
"k14" : 6}},
{"k22": { "k221" : "v122"}}
]
list_keys=[x for x in through(di,1)]
list_values=[x for x in through(di,2)]
list_keyval=[x for x in through(di,3)]
print("Key list: ",list_keys)
print("Values list (all, not excluding dict values): ",list_values)
print("all (Key,Value) pairs:", list_keyval)

what is the difference between findResults and collect in groovy?

Here is the code using collect
​def lst = [1,2,3,4];
def newlst = [];
newlst = lst.collect {element -> return element * element}
println(newlst);
Here is the code using findResults
def lst2 = [1,2,3,4];
def newlst2 = [];
newlst2 = lst2.findResults {element -> return element * element}
println(newlst2);
​Both seem to return [1, 4, 9, 16] so what is the difference? Thanks!
Basically the difference is how they deal with null values
collect when sees null will collect it, while findResults won't pick it.
In other words, the size of resulting collection is the same as the size of input when using collect.
Of course you could filter out the results but its an additional step
Here is a link to the example I've found in the internet
Example:
​def list = [1, 2, 3, 4]
println list.coll​​​​​​​​​​​​​​ect { it % 2 ? it : null}
// [1, null, 3, null]
println list.findResults { it % 2 ? it : null}​
// [1,3]
When we need to check if returned list is empty then findResults seem more useful. Thanks to Mark for the answer.
def list = [1, 2, 3, 4]
def l1 = list.collect { it % 100 == 0 ? it : null}
def l2 = list.findResults { it % 100 == 0 ? it : null}
if(l1){
println("not null/empty " + l1)
}
if(l2){
println("not null/empty " + l2)
}
​

Dictionary using distinct characters as values

I need to make a dictionary using the string list as keys and their distinct characters as values.
I have tried some functions and ended up with the following code but I cannot seem to add the string key into it
value=["check", "look", "try", "pop"]
print(value)
def distinct_characters(x):
for i in x:
yield dict (i=len(set(i)))
print (list(distinct_characters(value))
I would like to get
{ "check" : 4, "look" : 3, "try" : 3, "pop" : 2}
but I keep getting
{ "i" : 4, "i" : 3, "i" : 3, "i" : 2}
Well, string is itself an iterable, so don't call list on dicts instead call dict on list of tuples like below.
value=["check", "look", "try", "pop"]
print(value)
def distinct_characters(x):
for i in x:
yield (i, len(set(i)))
print(dict(distinct_characters(value)))
Output:
{'check': 4, 'look': 3, 'try': 3, 'pop': 2}
Consider the simple dictionary comprehension:
value = ["check", "look", "try", "pop"]
result = {key: len(set(key)) for key in value}
print(result)
Thanks for the replies
I needed to answer it as a function for a class exercise so I ended up using this code:
value=["check", "look", "try", "pop"]
print(value)
def distinct_characters(x):
for i in x:
yield (i, len(set(i)))
print(dict(distinct_characters(value)))
Thanks again

Fastest way to find all the indexes of maximum value in a list - Python

I am having list which as follows
input_list= [2, 3, 5, 2, 5, 1, 5]
I want to get all the indexes of maximum value. Need efficient solution. The output will be as follows.
output = [2,4,6] (The above list 5 is maximum value in a list)
I have tried by using below code
m = max(input_list)
output = [i for i, j in enumerate(a) if j == m]
I need to find any other optimum solution.
from collections import defaultdict
dic=defaultdict(list)
input_list=[]
for i in range(len(input_list)):
dic[input_list[i]]+=[i]
max_value = max(input_list)
Sol = dic[max_value]
You can use numpy (numpy arrays are very fast):
import numpy as np
input_list= np.array([2, 3, 5, 2, 5, 1, 5])
i, = np.where(input_list == np.max(input_list))
print(i)
Output:
[2 4 6]
Here's the approach which is described in comments. Even if you use some library, fundamentally you need to traverse at least once to solve this problem (considering input list is unsorted). So even lower bound for the algorithm would be Omega(size_of_list). If list is sorted we can leverage binary_search to solve the problem.
def max_indexes(l):
try:
assert l != []
max_element = l[0]
indexes = [0]
for index, element in enumerate(l[1:]):
if element > max_element:
max_element = element
indexes = [index + 1]
elif element == max_element:
indexes.append(index + 1)
return indexes
except AssertionError:
print ('input_list in empty')
Use a for loop for O(n) and iterating just once over the list resolution:
from itertools import islice
input_list= [2, 3, 5, 2, 5, 1, 5]
def max_indexes(l):
max_item = input_list[0]
indexes = [0]
for i, item in enumerate(islice(l, 1, None), 1):
if item < max_item:
continue
elif item > max_item:
max_item = item
indexes = [i]
elif item == max_item:
indexes.append(i)
return indexes
Here you have the live example
Think of it in this way, unless you iterate through the whole list once, which is O(n), n being the length of the list, you won't be able to compare the maximum with all values in the list, so the best you can do is O(n), which you already seems to be doing in your example.
So I am not sure you can do it faster than O(n) with the list approach.

How do I implement a comparator for a map in Groovy?

I have a map in Groovy:
['keyOfInterest' : 1, 'otherKey': 2]
There is a list containing a number of these maps. I want to know if a map exists in the list with keyOfInterest of a certain value.
If the data types were simple objects, I could use indexOf(), but I don't know how to do this with a more complicated type. E.g. (taken from the docs)
assert ['a', 'b', 'c', 'd', 'c'].indexOf('z') == -1 // 'z' is not in the list
I'd like to do something like:
def mapA = ['keyOfInterest' : 1, 'otherKey': 2]
def mapB = ['keyOfInterest' : 3, 'otherKey': 2]
def searchMap = ['keyOfInterest' : 1, 'otherKey': 5]
def list = [mapA, mapB]
assert list.indexOf(searchMap) == 0 // keyOfInterest == 1 for both mapA and searchMap
Is there a way to do this with more complicated objects, such as a map, easily?
While #dmahapatro is correct, and you can use find() to find the map in the list of maps that has the matching index... that's not what you asked for. So I'll show how you can get either the index of that entry in the list, or just whether a map with matching keyOfInterest exists.
def mapA = ['keyOfInterest' : 1, 'otherKey': 2]
def mapB = ['keyOfInterest' : 3, 'otherKey': 2]
def searchMap = ['keyOfInterest':1, 'otherKey': 55 ]
def list = [mapA, mapB]
// findIndexOf() returns the first index of the map that matches in the list, or -1 if none match
assert list.findIndexOf { it.keyOfInterest == searchMap.keyOfInterest } == 0
assert list.findIndexOf { it.keyOfInterest == 33 } == -1
// any() returns a boolean OR of all the closure results for each entry in the list.
assert list.any { it.keyOfInterest == searchMap.keyOfInterest } == true
assert list.any { it.keyOfInterest == 33 } == false
Note that there is no performance penalty for using one over the other as they all stop as soon as one match is found. find() gives you the most information, but if you're actually looking for the index or a boolean result, these others can also be used.
Simplest implementation would be to use find(). It returns null when criteria is not met in the supplied closure.
def mapA = ['keyOfInterest' : 1, 'otherKey': 2]
def mapB = ['keyOfInterest' : 3, 'otherKey': 2]
def list = [mapA, mapB]
assert list.find { it.keyOfInterest == 1 } == ['keyOfInterest':1, 'otherKey':2]
assert !list.find { it.keyOfInterest == 7 }

Resources