Compare list of lists

Hello, I’m trying to compare 2 lists of lists with such result

image

How would I do that? List.Contain and string.contain either don’t work or I don’t know how to use them properlyWires and tags.dyn (85.3 KB)

%D0%A1%D0%BD%D0%B8%D0%BC%D0%BE%D0%BA

There are multiple ways to approach this process! I personally avoid using boolmask/anytrue methods because it uses an excess of nodes that can be easily replaced with a simple python script. Not sure exactly how you want your data outputted but this is a pretty simple idea you might use.Capture

1 Like

Well, ok, it works for 1 list compared to multiple lists. But I have to compare multiple lists to multiple lists so what it would be list of lists as an output. How would I achieve it with this script?

Hi @mironov.boris,

You probably can keep going with String contains, just change the lacing to Cross-Product.
See attached, probably something like that?Make sure you search you shortest list against the longest

Cross-Product

1 Like
list = []
for i0 in IN[0]:
	for i1 in IN[1]:
		for ii1 in i1:
			if ii1 in i0:
				list.append(ii1)
OUT = list

just adding another for loop iterating through the first input would work for lists of lists then.

1 Like

Wait, it outputs elements instead of booleans and still there’s only one list :slightly_smiling_face: I’m not very familiar with python so it’s complicated for me to edit it by myself

well the idea was that you dont need the booleans xD
list =
for i0 in IN[0]:
for i1 in IN[1]:
for ii1 in i1:
if ii1 in i0:
list.append(True)
else:
list.append(False)
OUT = list
That will give you the booleans

Oh, ok, but now it says “expected an indeted block” and even in your example there’s one output list for both compared lists :slightly_smiling_face:

If list structure matters then something like this works, there’s easier ways to do it but this was the first thing that came to mind. Sorry forgot to format the code, this should be what you want then?

list = []
output = []
for i0 in IN[0]:
	for i1 in IN[1]:
		for ii1 in i1:
			if ii1 in i0:
				list.append(True)
			else:
				list.append(False)
		output.append(list)
		list = []
OUT = output

so what about multiple lists? didn’t manage to make it work :pensive:

Well. not quite, it manages to output lists but the comparasion is weird

Ok, I almost got what I intended to achieve, but instead of 4 lists it creates 16, why?

list =
output =
for i0 in IN[0]:
for i1 in IN[1]:
for ii0 in i0:
if ii0 in i1:
list.append(True)
else:
list.append(False)
output.append(list)
list =
OUT = output

It is getting the Cartesian product of the two lists being checked againt eachother (the same as cross product lacing) so it is comparing each nested list to each other nested list. I assumed that is what you were looking for but if not, perhaps you could give more details on what you need?

As far as I understand, that’s right, but for some reason your script doesn’t do that in my case. So I’ll show what I want to achieve lists.xlsx (9.0 KB)

image

Ok I see now!

output = [] #initiate output list
for ind,i0 in enumerate(IN[0]): #iterate through the first input
	output.append([]) #create an empty list to keep list structure
	for ii0 in i0: #iterate through each element in the sublist in the first input
		if ii0 in IN[1][ind]: #if element is in input 2 at the current sublist's index:
			output[ind].append(True) # add true to the current sublist in output
		else: #if element is not in sublist
			output[ind].append(False) #add false to the current sublist in output
OUT = output #return the 'output' list

5 Likes

Oh. man, I’m your fan now :smile: literally have been racking my brain the entire day. This topic will be preserved for the centuries, I suppose, for I haven’t found a single solution on the internet
And I should probably start learning python :thinking:

Glad it works. There are certainly ways to make this way better but I am still learning python myself. It is extremely helpful for dynamo!

This is completely unnecessary as @martin.scholl has already provided a great answer but I just wanted to show a couple of other python scripts that would work as well:

Because you are using if ii0 in IN[1][ind] in the if statement, you are already checking if the value ii0 is in the list to get a true/false. Therefore, you can cut out the repeats of appending if you just use the statement ii0 in IN[1][ind] as the argument for the append.

In other words, you could remove lines 5-8 and replace it with output[ind].append(ii0 in IN[1][ind])

To further shorten it, since the return of the for loop is now only a single line, you can combine the entire for loop into a definition of the variable output[ind]

I used a similar method but instead of enumerating one of the lists, I just zipped them together so that they are at equal indices as I run through them. Here is the final code:

mainList = IN[0]
checkList = IN[1]
OUT = []
for main, check in zip(mainList, checkList):
    OUT.append([m in check for m in main])

And for my own personal python practice, I tried the same function using lambda combined with mapping:

f = lambda main, check : [m in check for m in main]
OUT = map(f, IN[0], IN[1])

Results:

7 Likes

Very helpful! thanks for showing the improvement. I forgot to think about using lambda because I still do not understand the syntax involving it to well but those are really nice solutions I’m sure I will use in the future!

Or just this…
image

3 Likes