Issue when filtering list by A or B

Hi all,

I’m working on a script to make parts for a slab set out plan, and then hide all parts which aren’t concrete or blockwork so that only blockwork and precast are shown on the plans.

I manage to create the parts no worries, and then filter the “Material” parameter of the parts for the terms “CONC” OR “BLOCK”. The issue I’m having is that my output from the List.FilterByBoolMask nodes still contains parts that are blockwork and concrete, which causes undesirable walls to be hidden. See below:

Not quite sure what I’m doing wrong…I’ve been using dynamo for a couple of months now and I still can’t figure out the best methodology to filter a list by A OR B which is driving me a little crazy. I’ve spent a lot of time searching for related posts but haven’t stumbled upon the answer as of yet.

If someone could please point me in the right direction or let me know why this is failing it would be much appreciated.

Thanks in advance!

Mark Parts_V2.dyn (46.3 KB)

From what I can see, you are splitting your initial list of walls into two to check for CONC and BLOCK. It is not efficient and it will make you have two lists of filtered elements. Your problem can be solved combining the two in results from Filter by boolean mask.
If prefer something more efficient, go for something more like this:

1 Like

@architectcoding

THANK YOU SO MUCH!

I take it that I can’t use the OOTB String.Contains node because its searchFor input requires a string, whereas I’m feeding in a list of strings?

The only issue I’m now having is that this node doesn’t have an IgnoreCase input like the OOTB node. Due to people naming materials as they wish, I have materials such as Concrete, CONCRETE, concrete…etc.

I take it the only way around this is to add all variants of the spelling to my FilterList input, as per the below:

1

Thanks again!!!

That’s correct, but you have found a workaround it, that is splicing the list of elements to check to single elements. If you don’t have many things to test, it is a workable solution, but not optimal.

Hahahahaha, I know, how difficult is to make everyone to settle down to one naming system! Well, there are other solutions, but some programming knowledge is required.


image
Here is the code:

# The inputs to this node will be stored as a list in the IN variables.
data = [x.lower() for x in IN[0]]
matchList = [x.lower() for x in IN[1]]

boolMask = []

# Function to check if string contains substring
def contains(str, inputList):
	for element in inputList:
		if element in str:
			return True

# Check if strings in list are contained in leements of another list
for d in data:
	if contains(d, matchList):
		boolMask.append(True)
	else:
		boolMask.append(False)

# Assign your output to the OUT variable.
OUT = boolMask
1 Like

@architectcoding,

Thanks so much for taking the time to provide such an informative answer.

  • Indeed. It works in this scenario, but as you mention, it isn’t optimal.

I’m just beginning to explore python so it’s still a little over my head :sweat_smile:

But I will have a play around with the script you sent through and see if I can learn a thing or two. Thanks again for such an in depth answer!

@architectcoding

Just had the opportunity to sit down and play with the code you so kindly shared.

Works an absolute treat and will be of major benefit - can’t thank you enough.

Wish I could understand what exactly how you’ve achieved this but python is beyond me at this stage :expressionless: although people like yourself definitely go to show the benefits of learning. I’ll have to take the leap sooner or later.

Thanks again for taking the time to provide such an in-depth response and teaching me a thing or two!

Glad it helped mate!

Well, the community is doing a great job. I started in Python not that long ago, and it was thanks to guys in this community that helped me to see the value of learning a programming language.

Yeah! Python is not hard and you will uncover a whole new level of fun and stuff to learn haha.

No worries! Let us know when you need something and we will be here to help!

1 Like

Hey again @architectcoding

Sorry to bother you but the python node seems to spitting out an error now… No idea why as it was working perfectly fine previously… The error message I’m recieving is shown below…

Error

Any suggestions as to what could now be causing the error?

It seems weird as it was running perfectly fine previously…

Thanks!

Sorry I think I jumped the gun there.

There was an error with the list of material parts I was feeding into the Python Script node.

There was a null value within the IN[0] list which was causing the error.

By cleaning the list prior to feeding it into the Python Script node I was able to get the node working again.

Sorry for the hassle and thanks again!

Nice that you made it work! Well, as you figured it out, it was because a null value doesn’t have the lower() method. Added a few lines in the script to handle this case, and a link to list comprehension, useful in this case:

# The inputs to this node will be stored as a list in the IN variables.
data = [x.lower() if x != None else None for x in IN[0]]
matchList = [x.lower() if x != None else None for x in IN[1]]

boolMask = []

# Function to check if string contains substring
def contains(str, inputList):
	for element in inputList:
		try:
			if element in str:
				return True
		except:
			pass # You can add some error message here instead of pass

# Check if strings in list are contained in elements of another list
for d in data:
	if contains(d, matchList):
		boolMask.append(True)
	else:
		boolMask.append(False)

# Assign your output to the OUT variable.
OUT = boolMask
1 Like

@architectcoding

You are a legend!

Thanks for another great explanation and sharing your code. Really helps to get a better understanding of python. That DataFlair resource is great also. Much appreciated.