How to compare elements of nested lists between each other? - python-2.7

I try to compare elements of nested list between each other. Let's say I have the following list:
list1 = [['v1', '1', '2'],['v1', '2', '2'], ['v2', '1'], ['v3'], ['v4', '1'], ['v4', '2']]
and I would like to reach to:
result = [['v1', '2'],['v1', '2'],['v2', '1'], ['v3'], ['v4'], ['v4']]
I've done a small code, but it does not look to work very well.
for i in range(1, len(list1) - 1):
previousone = list1[i-1]
currentone = list1[i]
nextone = list1[i+1]
lenprevious = len(previousone)
lencurrent = len(currentone)
lennext = len(nextone)
minlen = min(lenprevious,lencurrent,lennext) -1
common = ''
for j in range(minlen):
if j == 0:
if previousone[j] == currentone[j]:
common += str(previousone[j])
if previousone[j] != currentone[j]:
if currentone[j] == nextone[j]:
common += str(currentone[j])
else:
common += currentone
break
else:
if common != '':
if previousone[j] == currentone[j]:
common.join('_',str(nextone[j]))
else:
if currentone[j] == nextone[j]:
common.join('_',str(nextone[j]))
else:
break
else:
break
print common
result.append(common)
The idea, is to compare the 1st element of the sub-list vs the 1st element of the previous sub-list. If no match, then we compare with the next sub-list. If no match, we get in common the 1st element of the current sub-list.
Then, if it's matching, we do the same for the next element of the sub-list and so one until the last one. In the end, I want to have in common, a list of the common elements if any, if not I want the current sub-list.
Does anyone has any idea how to make it work? Thanks in advance!
EDIT ::
The logic would be:
Iteration 1 -> Previous : ['v1', '1', '2'] and Current : ['v1', '2', '2'] and Next : ['v2', '1']
We compare each element from each list.
First, we compare the Previous and the Current.
First element of those lists are 'v1', so we append 'v1' in result and we go to the next element, here '1' and '2'.
They are not the same so we pass until the next element, which are '2' and '2': identical.
We append in result to get Result :
[['v1', '2'], ['v1', '2'], [], [], [], []]
Iteration 2 -> Previous : ['v1', '2', '2'] and Current : ['v2', '1'] and Next : ['v3']
First we compare Previous and Current. 'v1' different from 'v2'.
So we compare Current and Next. 'v2' different from 'v3'.
So we append in result the current and we get:
[['v1', '2'], ['v1', '2'], ['v2', '1'], [], [], []]
Iteration 3 -> Previous : ['v2', '1'] and Current : ['v3'] and Next : ['v4', '1']
Same as above, 'v2' different from 'v3' and 'v3' different from 'v4' so we append the current and get:
[['v1', '2'], ['v1', '2'], ['v2', '1'], ['v3'], [], []]
Iteration 4 -> Previous : ['v3'] and Current : ['v4', '1'] and Next: ['v4', '2']
'v3' different from 'v4' so we compare Current and Next: 'v4' is common so we append 'v4':
[['v1', '2'], ['v1', '2'], ['v2', '1'], ['v3'], ['v4'], []]
Iteration 5 -> Previous : ['v4', '1'] and Current : ['v4', '2'] and Next : ??
'v4' is common so we append 'v4' and get the final result:
Result: [['v1', '2'], ['v1', '2'], ['v2', '1'], ['v3'], ['v4'], ['v4']]
But I do not know how to reach there..

Below is the implementation according to your desired result,
Core Logic
def intersection(lst1, lst2):
return list(set(lst1) & set(lst2))
list1 = [['v1', '1', '2'],['v1', '2', '2'], ['v2', '1'], ['v3'], ['v4', '1'], ['v4', '2']]
result = []
list_len = len(list1)
if list_len == 0:
pass
elif list_len == 1:
result.append(list1)
else:
for i in range(list_len):
if i == 0:
current = list1[i]
next = list1[i+1]
print("Iteration {} -> Previous : No previous available Current : {} Next: {}".format(i, current, next))
if current[0] == next[0]:
result.append(intersection(current, next))
else:
result.append(current)
elif i == list_len - 1:
previous = list1[i-1]
current = list1[i]
print("Iteration {} -> Previous : {} Current : {} Next: No next available".format(i, previous, current))
if current[0] != previous[0]:
result.append(current)
else:
result.append(intersection(current, previous))
else:
previous = list1[i-1]
current = list1[i]
next = list1[i+1]
print("Iteration {} -> Previous : {} Current : {} Next: {}".format(i, previous, current, next))
if current[0] == previous[0]:
result.append(intersection(current, previous))
else:
if current[0] == next[0]:
result.append(intersection(current, next))
else:
result.append(current)
print("Result : {}".format(result))
Output
Iteration 0 -> Previous : No previous available Current : ['v1', '1', '2'] Next: ['v1', '2', '2']
Iteration 1 -> Previous : ['v1', '1', '2'] Current : ['v1', '2', '2'] Next: ['v2', '1']
Iteration 2 -> Previous : ['v1', '2', '2'] Current : ['v2', '1'] Next: ['v3']
Iteration 3 -> Previous : ['v2', '1'] Current : ['v3'] Next: ['v4', '1']
Iteration 4 -> Previous : ['v3'] Current : ['v4', '1'] Next: ['v4', '2']
Iteration 5 -> Previous : ['v4', '1'] Current : ['v4', '2'] Next: No next available
Result : [['v1', '2'], ['v1', '2'], ['v2', '1'], ['v3'], ['v4'], ['v4']]

Related

compare items in Map and List

I have a map(radioValue) which holds list of question id, and answer value, also a answerTable holds lot of Answer Object.When submit button triggered, I would like to compare radioValue id and answerTable. If id in radioValue exists in answerTable, call edit api , otherwise call edit api
List<ChecklistAnswerItem> answerTable =
await _repository.selectChecklistAnswerItemsList();
for (var key in radioValue.keys) {
if (radioValue[key] != "") {
for (var i in answerTable) {
if (key == i.sectionItemId) {
// if key(question id) same with i.sectionItemId(answer id)
// call edit api
} else {
// call create api
}
}
}
}
I came out with this code, but it is wrong. If answerTable is empty, both api will not be called.
Latest code
for (var key in radioValue.keys) {
if (radioValue[key] != "") {
var answer =
answerTable.firstWhere((a) => a.checklistsectionItem?.id == key);
print(answer);
//call create api
} else {
//call edit api
}
}
Error
E/flutter (27156): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: Bad state: No element
E/flutter (27156): #0 ListMixin.firstWhere (dart:collection/list.dart:167:5)
Assuming the Answer model is this:
class Answer {
String answerId;
String questionId;
Answer({this.answerId, this.questionId});
}
And the lists are:
List<String> questionIds = ['1', '2', '3', '4'];
List<Answer> answerIds = [
Answer(answerId: '1', questionId: '1'),
Answer(answerId: '73', questionId: '3'),
Answer(answerId: '43', questionId: '3'),
Answer(answerId: '123', questionId: '14'),
Answer(answerId: '322', questionId: '88'),
Answer(answerId: '13', questionId: '123'),
Answer(answerId: '32', questionId: '355'),
];
then the checks can be:
void checkLists() {
var specificQuestionId = '1';
// This checks if there are any question IDs in answers list
if (answerIds.any((a) => questionIds.contains(a.questionId))) {
print('Yes there are question ids in answers list');
}
// This checks if there is a specific ID in answers list
if (answerIds.any((a) => a.questionId == specificQuestionId)) {
print('Yes the question id is in answers list');
// if you want to get the value of the answer you can use firstWhere
var answer = answerIds.firstWhere((a) => a.questionId == specificQuestionId);
}
}

How to merge list of dict with same keys?

I have a list:
list=[{'Query': 'documents'}, {'entity': 'a'}, {'value': 'b'}, {'entity': 'c'}, {'value': 'd'}, {'records':21}]
I want following o/p:
d={'Query': ['documents'],'entity': ['a','c'],'value': ['b','d'],'records':[21]}
try this code :
list=[{'Query': 'documents'}, {'entity': 'a'}, {'value': 'b'}, {'entity': 'c'}, {'value': 'd'}, {'records':21}]
d={}
for i in list :
for j,k in i.items():
l = []
if j in d:
l = d[j]
l.append(k)
d[j] = l
else:
l.append(str(k))
d[j]=l
print(d)
output:
{'records': ['21'], 'value': ['b', 'd'], 'entity': ['a', 'c'], 'Query': ['documents']}

How to add list of tuple value in list of dictionary using pyspark?

I have 2 rdd, one as list of dictionary and second as list of tuple shown as below -
rdd1 = [{'id1', ['string', 'string', count]}, {'id2', ['string', 'string', count]}, {'id3', ['string', 'string', count]}]
rdd2 = [(id1, count), (id2, count), (id3, count)]
Now i want to add count from rdd2 to rdd1 if id from rdd2 matches with rdd1.
Can you please help me to achieve this?
Thank you in advance.
Although Gates answer is correct, you should try to avoid using for loops when working with RDD's. Operations on RDDs are parallelized and are much faster compared to for loops when working with big datasets.You can achieve the same by joining the two RDDs and reformatting the output:
rdd1 = sc.parallelize([{'id1':['string','string',1]}, {'id2':['string','string',2]}, {'id3':['string','string',3]}])
rdd2 = sc.parallelize([('id1',2), ('id2',4), ('id3',6), ('id4',8)])
rdd_joined = rdd1.flatMap(lambda x:x.items()).join(rdd2)
rdd_reformatted = rdd_joined.map(lambda (x,(y,z)):{x:y[:-1]+[y[-1]+z]})
rdd_reformatted.collect() gives as output:
[{'id2': ['string', 'string', 6]},
{'id3': ['string', 'string', 9]},
{'id1': ['string', 'string', 3]}]
I hope this helps.
rdd1 = [{'id1':['string','string',1]}, {'id2':['string','string',2]}, {'id3':['string','string',3]}]
rdd2 = [('id1',2), ('id2',4), ('id3',6), ('id4',8)]
for each in rdd2:
there = False
position = 0
for ele in rdd1:
if each[0] in ele.keys():
#now increment the count
original = rdd1[position]
originalList = original[each[0]]
#updating the 3rd element
newList = originalList
newList[2] = originalList[2] + each[1]
#update the new list to key
updated = { each[0] : newList }
rdd1[position] = updated
there = True
break
position = position + 1
print rdd1
#output: [{'id1': ['string', 'string', 3]}, {'id2': ['string', 'string', 6]}, {'id3': ['string', 'string', 9]}]

Find element in a nested list and transform (groovy)

If I have a Groovy nested list such as:
List list = ['a', 'b', 'c', ['d', 'e', ['f']]]
I would like to be able to search the list for a particular element, say 'd' and then transform that element to something else such as ['g', 'h'] so that the new list looks like:
['a', 'b', 'c', [['g', 'h'], 'e', ['f']]]
Like this??
List list = ['a', 'b', 'c', ['d', 'e', ['f']]]
assert list.collectNested{
if (it == 'd') {
['g', 'h']
} else {
it
}
} == ['a', 'b', 'c', [['g', 'h'], 'e', ['f']]]
Use following generic approach :-
def findAndReplace(def listValue, def listIndex, def valueToCompare, def valueToReplace, def originalList) {
if(listValue instanceof List) {
listValue.eachWithIndex { insideListValue, insideListIndex ->
findAndReplace(insideListValue, insideListIndex, valueToCompare, valueToReplace, listValue)
}
}else if(listValue == valueToCompare) {
originalList[listIndex] = valueToReplace
}
}
List originalList = ['a', 'b', 'c', ['d', 'e', ['f']]]
def valueToCompare = 'd'
def valueToReplace = ['g', 'h']
originalList.eachWithIndex { listValue, listIndex ->
findAndReplace(listValue, listIndex, valueToCompare, valueToReplace, originalList)
}
println originalList
Output: [a, b, c, [[g, h], e, [f]]]
Hope it will help you...:)

Groovy/Grails groupBy dynamic list of fieldnames

i want to group a list of objects by a dynamic list of fields (given by name). I'll try to explain it with an example.
Let's say I have a class looking similar to this:
def SomeClass{
String one
String two
String three
String four
//etc..
}
Now I have a changeable list of 1-4 field names, therefore hardcoding is not an option, like this:
def fields = ["one", "two"]
//or
def fields2 = ["two", "three", "four"]
I want to sort lists of SomeClass, and as result I need a map with a list of values as key and the objects as value; Looking like this:
//group by fields:
def result = [[someClass.one, someClass.two]:[List<SomeClass>],...]
//group by fields2:
def result2 = [[someClass.two, someClass.three, someClass.four]:[List<SomeClass>],...]
I tried splitting the fields and create closures for .groupBy(), but I retrieve a nested Map.
With .collectEntries() i'm not sure how to pass a changeable list of fields to the closure.
The lists I want to sort contain around 500-10000 elements, with 1-4 fields I want to group by.
You can use groupBy with a Closure and collect your fields inside it:
import groovy.transform.*
#Canonical
class SomeClass{
String one
String two
String three
}
List<SomeClass> list = [
new SomeClass('a', '1', 'i'),
new SomeClass('a', '1', 'ii'),
new SomeClass('a', '2', 'i'),
new SomeClass('a', '2', 'ii'),
new SomeClass('a', '3', 'i'),
]
def fields = ['one', 'two']
Map<List<String>,List<SomeClass>> grouped = list.groupBy { o -> fields.collect { o."$it" } }
assert grouped == [
['a', '1']:[new SomeClass('a', '1', 'i'), new SomeClass('a', '1', 'ii')],
['a', '2']:[new SomeClass('a', '2', 'i'), new SomeClass('a', '2', 'ii')],
['a', '3']:[new SomeClass('a', '3', 'i')]
]