7
\$\begingroup\$

I want to construct a string from several substrings, each one of those with a different delimiter. If the string is present, the delimiter and the string should be added, if not, none of them should be added.

This is my current code that looks a bit dirty to me:

def my_join(major, minor, patch=None, pre_release=None, build=None, revision=None):
 version = '.'.join(filter(None,(major, minor, patch)))
 if pre_release: version += '-%s' % pre_release
 if build: version += '+b%s' % build
 if revision: version += '.%s' % revision
 return version
my_join('0', '1',pre_release='alpha')
'0.1-alpha'
my_join('2','3','4', build='567', revision='aabbcc440')
'2.3.4+b567.aabbcc440'

My problem is basically an extension of join 4 strings to the one if they are not empty in python with the addition of using different delimiter strings.

asked Aug 27, 2015 at 12:30
\$\endgroup\$
0

4 Answers 4

8
\$\begingroup\$

It doesn't look too bad to me; I'd make a few changes.

def my_join(major, minor, patch=None, prerelease=None,
 build=None, revision=None):
 version_parts = ['.'.join((major, minor, patch or ''))]
 if prerelease:
 version_parts.append('-%s' % prerelease)
 if build:
 version_parts.append('+b%s' % build)
 if revision:
 version_parts.append('.%s' % revision)
 version = ''.join(version_parts)
 return version

Instead of building the string piece-by-piece, this code adds the needed parts to a list which is then joined at the end. I also removed the overpowered call to filter, and instead used or to make the patch value be '' if patch is False-ish, as it would be if patch is None.

answered Aug 27, 2015 at 13:21
\$\endgroup\$
4
\$\begingroup\$

Your mileage may vary on whether this is an improvement but you can use the ternary operator:

version += '-%s' % pre_release if pre_release else ''
version += '+b%s' % build if build else ''
version += '.%s' % revision if revision else ''

I also think you should give a better name than my_join and add a docstring explaining your method.

def version_name(major, minor, patch=None, pre_release=None, build=None, revision=None):
 """When passed version details, will create a version name string."""

You didn't explain the intent so I might be misunderstanding the exact usage.

answered Aug 27, 2015 at 13:10
\$\endgroup\$
2
\$\begingroup\$

Opportunistic, but shorter way to do this:

import re
def format_version(major, minor, patch=None,
 pre_release=None, build=None, revision=None):
 return re.sub(r'(:?[\.-]|\+b)None', '',
 '{major}.{minor}.{patch}-{pre_release}+b{build}.{revision}'
 .format(**locals()))

This is opportunistic because it may fail in some "strange" situations, for example, if someone will literally pas the string 'None' as one of the arguments, however, I'd consider this to be too unlikely to be bothered with.

answered Aug 28, 2015 at 12:11
\$\endgroup\$
1
\$\begingroup\$

I'm not sure this makes it any better, but it does show one way to convert it to be a one line return:

def my_join(major, minor, patch=None, pre_release=None, build=None, revision=None):
 return "%s%s%s%s" % (
 '.'.join(filter(None,(major, minor, patch, pre_release))),
 ('-%s' % pre_release) if pre_release else '', 
 ('+b%s' % build) if build else '',
 ('.%s' % revision) if revision else '')

It does though remove the string concatenations.

answered Aug 27, 2015 at 12:33
\$\endgroup\$
1
  • \$\begingroup\$ Hmm, I think string.format is a little more clear, but, that looks better \$\endgroup\$ Commented Aug 27, 2015 at 12:36

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.