Select to view content in your preferred language

Modify feature class file name using f string

702
9
Jump to solution
a week ago
SeanLukacs
Occasional Contributor

Hello, I am pretty new with using python in Pro.  I need to modify feature class output names as they are being generated, or after they are created. 

 

I have a list of features in a feature dataset (since this is a list, I am assuming using listFeatureClass, for loop, and f strings is how I cycle through the layers)

EX_feature1

EX_feature2

EX_feature3

I want to remove the "EX_" from the feature class name and add "TR" in its place.

Is this a strip function?  can that be applied to fc names? Thanks in advance!

 

0 Kudos
2 Solutions

Accepted Solutions
DanPatterson
MVP Esteemed Contributor

replace should work

fcs = ["c:/path/EX_feature1","c:/path/EX_feature2", "c:/path/EX_feature3"]

out_fcs = [i.replace("EX_", "TR") for i in fcs]

out_fcs
['c:/path/TRfeature1', 'c:/path/TRfeature2', 'c:/path/TRfeature3']

... sort of retired...

View solution in original post

HaydenWelch
MVP Regular Contributor

If you know you just need to replace the first 3 characters (say it was a state code with an underscore or something) you could also do: 


out_fcs = [f"TR{fc[3:]}" for fc in fcs]

 

Using replace can sometimes burn you since by default it replaces *all* matching substrings unless you specify a limit. Meaning "aaabbbaaa".replace("a", "b") will give you "bbbbbbbbb" or "tr_tracks".replace("tr", "ex") would give you "ex_exacks"

View solution in original post

9 Replies
DanPatterson
MVP Esteemed Contributor

replace should work

fcs = ["c:/path/EX_feature1","c:/path/EX_feature2", "c:/path/EX_feature3"]

out_fcs = [i.replace("EX_", "TR") for i in fcs]

out_fcs
['c:/path/TRfeature1', 'c:/path/TRfeature2', 'c:/path/TRfeature3']

... sort of retired...
HaydenWelch
MVP Regular Contributor

If you know you just need to replace the first 3 characters (say it was a state code with an underscore or something) you could also do: 


out_fcs = [f"TR{fc[3:]}" for fc in fcs]

 

Using replace can sometimes burn you since by default it replaces *all* matching substrings unless you specify a limit. Meaning "aaabbbaaa".replace("a", "b") will give you "bbbbbbbbb" or "tr_tracks".replace("tr", "ex") would give you "ex_exacks"

SeanLukacs
Occasional Contributor

Thank you!  Is your example setting the output variable?  So I am clipping several layers and then renaming them to exclude the first 3 characters and replace with a different amount of characters, would that still work?

ex. "EX_" gets removed and I add in "TR100yr_".  so then my version of your line looks like outFeature = [f"TR100yr_{fc[3:]}" for fc in fcs].  Is the "3" just the number of characters to replace or an index?

HaydenWelch
MVP Regular Contributor

It is! In Python, strings implement the Sequence protocol, so you can iterate them and slice them like lists. The [3:] syntax is a slice that starts after the 3rd element and runs to the end. you can also truncate the last 3 with [3:-3] or get every other character between the first and last 3 with [3:-3:2]

>>> text = "abc_hello-world"
>>> text[3:]
... '_hello-world'
>>> text[3:-3]
... '_hello-wo'
>>> text[3:-3:2]
... '_el-o'

 

SeanLukacs
Occasional Contributor

@HaydenWelch That seemed to do the trick for my use case, thank you!

SeanLukacs
Occasional Contributor

Thank you!

0 Kudos
TylerT
by
Frequent Contributor

@SeanLukacs,
If you need a bit more robustness on future data sets you could look at regex substitution (re.sub()).  re.sub() will gracefully handle start matches, multiple matches, and non-matches with about the same amount of code.  Here's an example:

import re

fcs = [
    "EX_feature1",
    "EX_feature2",
    "feature4",
    "EX_feature5_EX_",
]
print(f"Original: {fcs}")
print(f'string replace: {[i.replace("EX_", "TR_") for i in fcs]}')
print(f'string slicer: {[f"TR_{fc[3:]}" for fc in fcs]}')
print(f"regex substitution: {[re.sub(r'^EX_', 'TR_', fc) for fc in fcs]}")

Output:

Original: ['EX_feature1', 'EX_feature2', 'feature4', 'EX_feature5_EX_']
string replace: ['TR_feature1', 'TR_feature2', 'feature4', 'TR_feature5_TR_']
string slicer: ['TR_feature1', 'TR_feature2', 'TR_ture4', 'TR_feature5_EX_']
regex substitution: ['TR_feature1', 'TR_feature2', 'feature4', 'TR_feature5_EX_']


<Note: I changed from required 'TR' to 'TR_' for readability in this example only.>

HTH,

Tyler


SeanLukacs
Occasional Contributor

@TylerT Thanks for that!  

0 Kudos
TylerT
by
Frequent Contributor

@SeanLukacs ,
I noticed in the Python docs that `string.replace()` has an optional count keyword giving it a bit more flexibility.  If keyword count is passed, only the first count occurrences are replaced.  This might be useful for your case also.

Tyler

0 Kudos