How to - Split a string containing letters and numbers

Hello All,

I have search long as hard and haven’t been able to find a smart / short solution to the following issue.

All i’m trying to do is split strings when it changes from letters to numbers.

ie. from the above i’d want to obtain a list formatted as;

List
0

[0] CB
[1] 100

1

[0] CL
[1] 105

PLEASE NOTE: This is NOT as simple as removing a certain number of numbers / characters from each end as there will not always be 2 letters at the start and 3 numbers at the end, it changes. It will always be letters followed by numbers though, so i could have ABCDEFG200.

Any help with this would be much appreciated.

I ended up with a massive dynamo workflow that still didn’t work and i feel like can probably be done really easily if you know how!

Thanks,
Jack.

There should be some simple solution to this but, the solution that comes to my mind is to

  1. Create a list with strings(0-9)
    2.create a for or while loop to see if the element is in list
    3.if yes get the index of that letter and split at index.

Hi Saju,

Unfortunately i’m not familiar with loops.

I had tried something quite similar with a list of strings (0-9). Looking to see if any of those numbers were in the string and then counting the “true” results but this doesn’t work when you have multiple occurrences of the same number and i couldn’t figure out how to get the occurrences to work for my scenario. This solution was a very long winded solution anyway so i gave up lol

Essentially i just need to split the string 1 character before the value is a number.

Think i’ve crack it with ‘FindRegularExpression’ node. Seems to be working perfectly!

3 Likes

Here’s an ootb option that checks for upper/lowercase matches (numbers).

6 Likes

Nice technique! Took me a little while to understand what it was doing (thanks for showing the watch nodes lol very helpful).


Another version OOTB.
How did you combine the 2 lists to get what you mentioned ?

List
0

[0] CB
[1] 100

1

[0] CL
[1] 105

I didn’t need to get the list in that format in the end. I just needed the text / numbers split up so i could alter the string and input other bits;

1 Like

Just for clarity, the String.Replace - replaceWith input is just a blank string;

image

Is there a way to search a string from back to front for any character that’s not a number and split it if it finds it at that point?

Hi @vanman,

You could also use python code to split numbers from string. See below:

import sys
import clr
import re
clr.AddReference(‘ProtoGeometry’)
from Autodesk.DesignScript.Geometry import *

aList = IN[0]

numsList =
stList =

for i in aList:
stringList = “”.join(re.split("[^a-zA-Z]", i))
stList.append(stringList)
numbersList = “”.join(re.split("[^0-9]
", i))
numsList.append(numbersList)

OUT = numsList, stList

image

the result would be:

image

It always separates numbers from the strings no matter where they located:

image

Hope that helps!

interesting! thank you but I’m more after trying to find the first character thats not a number in the string then splitting from the back. Or just removing that that number then I can search to remove the rest from that string.

I tried yours but gave me below and I’m after the blue on the right.

hi @vanman
is this what you’re looking for:

thanks viktor, but I dont think so. Or I’m typing something wrong. I dont know python but I think I’d maybe need a isnumber or isdigit method to get it to split at the first thing thats not a number from the back

import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

dataEnteringNode = IN

output = []
for string in IN[0]:
	compoundlst =  []
	i = len(string)-1
	while i>=0:
		if not string[i].isalpha():
			first = string[:i-1]
			second = string[i-1:]
			compoundlst.append(first)
			compoundlst.append(second)
			break
		else: compoundlst.append(string)
		i-=1
	output.append(compoundlst)
	
OUT = output

Ok, my bad. And isalpha isn’t gonna help in this case.

you can give that a try:

# Load the Python Standard and DesignScript Libraries
import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

# The inputs to this node will be stored as a list in the IN variables.
dataEnteringNode = IN

output = []
numbers = ["0","1","2","3","4","4","6","7","8","9"]
for string in IN[0]:
	i = len(string)-1
	rest =[]
	digits = [] 
	while i>=0:
		if string[i] not in numbers:
			rest = string[:i-1]
			digits = string[i+1:]
			break	
		i-=1
	compoundlst = [rest,digits]
	output.append(compoundlst)
# Assign your output to the OUT variable.
OUT = output

you don’t need the protogeometry import obviously, but I was too lazy to remove it

thanks victor. I might be explaining poorly. I’m trying to find a method that will look at a strings characters from reverse and find the first thing that isnt a number and then split it. So my 1 list would split into the 2 and 3 lists I’ve done as an example.


Below stuff is me trying to work it out with dynamo which is tricky

Got it… is it iron clad? I’m not sure but stoked

yeah, if you need them as separate lists there are multiple ways to go:


I guess I should’ve shown that earlier

Thanks Victor. The first list in yours should be.

  1. 10AB
  2. A1B-C
  3. A.B1.
  4. aabbcc
  5. a

the other list the left over numbers

Hi @vanman , try this:

split = String.Split(x,"");
to_numbers = List.Clean(String.ToNumber(split));
null_to_str = to_numbers==null?"null":to_numbers;
rank_check = List.Count(null_to_str<1>)==1?"not null":null_to_str;
null_idx = List.Clean(List.LastItem(List.AllIndicesOf(rank_check<1>,"null")<1>));
null_replace = null_idx==null?-1:null_idx;
count = String.Length(x)-(null_replace+1);
lst1 = String.Remove(x,null_replace+1,count);
lst2 = String.Substring(x,null_replace+1,count);
out = List.Transpose([lst1,lst2]);
1 Like