Better Bruteforce Get Parameter?

What do you think of this for getting parameters that cannot be gotten with Element.GetParameterValueByName ? Is there a more efficient method?

def get_param(data, prefix):
  prefix = prefix + " : "
  results = []
  for lst in data:
    for item in lst:
      if item.startswith(prefix):
        param = item[len(prefix):]
        results.append(param)
  return results
    
param = get_param(IN[0], IN[1])    
OUT = param

Bakery’s Bruteforce Get Parameter via String Split V2 seems heavy, especially for big datasets.

Thanks to Claude 2 for the code coaching! It is fantastic to succinctly work out one’s logic and write Python.

It will write summaries for documenting one’s code, too.

You could do this in one line as a list comprehension

OUT =  [j for i, j in (param.split(" : ") for param in IN[0]) if i == IN[1]]

or a dictionary comprehension

param_dict = {k: v for k, v in (param.split(" : ") for param in IN[0])}
OUT = param_dict.get(IN[1])
1 Like

just adding a new idea on how to get this by splitting the string with .split() and the putting it to a new list

the script is asking if one part is equal to the given string which is IN[1] then out the corresponding part as a result.

data = IN[0]

result = []
other_value = []

for item in data:
    parts = item.split(":")
    if parts[0].strip() == IN[1]:
        n = parts[1]
        result.append(n)
    else:
        other_value.append(parts[1])

OUT = result

I refactored it to make sure there is no leading space and to run in Python 2 (Revit 2022.1)

data = IN[0]
result = []
for outer in data:
  for string in outer:
    parts = string.split(" : ")
    if parts[0] == IN[1]:
      result.append(parts[1])
    else:
      result.append(None)  
OUT = result

Is that any more efficient? I suppose I can use Tuneup to compare the different methods. Thanks also to @Mike.Buttery for the comprehension.


List comprehension is a little faster, according to Tuneup.

data = IN[0]
result = [parts[1] if parts[0] == IN[1] else None  
           for outer in data 
           for string in outer  
           for parts in [string.split(" : ")]]
OUT = result

versus

data = IN[0]
result = []
for outer in data:
  for string in outer:
    parts = string.split(" : ")
    if parts[0] == IN[1]:
      result.append(parts[1])
    else:
      result.append(None)  
OUT = result

Edit: those Python functions are WRONG (do not use).

if you’re worried the white space before and after the segregated strings, on my original code the .strip() method will take care of that.
if parts[0].strip() == IN[1]:
you can read more about in here: https://www.w3schools.com/python/ref_string_strip.asp

anyway, there’s a lot of way you can achieve what you were trying to do, this is just one way to do that. I think your original script works as well as the list comprehension by Mr. Mike.

I didn’t have the logic correct if the parameter doesn’t exist in the element data.

I asked Claude 2 in my conversation with it:
in[0] is a list with many sublists of varying lengths.

OUT needs to have the same length as in[0]

each element of OUT shall be the result if there is a match, or null

Resulting code seems to work (even though I could never come up with it – thanks, AI):

OUT = [None] * len(IN[0])

for i, outer in enumerate(IN[0]):
  for string in outer: 
    parts = string.split(" : ")
    if parts[0] == IN[1]:
      OUT[i] = parts[1]
      break

We can see here that Stairs has no Area parameter so should return null. Quicker, too, because it has break.

.strip() is a useful function, and I am glad to learn about it :nerd_face:. If we are making a generic node, we want to preserve the original data, which may contain leading and trailing spaces. Let’s hope the data don’t have an extra " : "!

Gotta work on that…

Solved?

OUT = [None] * len(IN[0])

for i, outer in enumerate(IN[0]):
  for string in outer: 
    parts = string.split(" : ")
    if parts[0] == IN[1]:
      OUT[i] = " : ".join(parts[1:])
      break

The key points:

  • Initialize OUT with Nones
  • Split string on " : "
  • If prefix matches, join remaining parts
  • Break inner loop to move to next outer item

This cleanly handles:

  • Initializing OUT with correct length
  • Splitting once on " : "
  • Getting full remainder string if matched
  • Setting OUT to result or None

By breaking after setting OUT, it avoids unnecessary further processing.


According to Tuneup, the two nodes plus this Python took less than 3 seconds versus around 60 seconds for Bruteforce Get Parameter Value by Name

I have used the Bruteforce nodes for their convenience but will use this method in the future.