【问题标题】:Other ways to do this for loop?其他方法可以做到这一点 for 循环?
【发布时间】:2018-08-28 23:27:23
【问题描述】:

我只是想知道是否有一种方法可以改进这个 for 循环,以某种方式跳过那些。

var String 可以有更多参数,它们的顺序可以随意。
为了用实际值替换参数,我需要:

  1. 拆分它
  2. 检查参数是什么以及在哪个位置

这是一个关于我的想法的综合示例:

String = "{FullDate}_{Month}_{Day}_{Year}_{ElementID}_{ElementCD}"
String_split = String.split("_")

for params in range(len(String_split)):

    if "FullDate" in String_split[params]:
        # Do something
    elif "Name" in String_split[params]:
        # Do something
    elif "ElementID" in String_split[params]:
        # Do something
    elif "ElementCD" in String_split[params]:
        # Do something
    elif "Year" in String_split[params]:
        # Do something
    elif "Day" in String_split[params]:
        # Do something
    elif "Month" in String_split[params]:
        # Do something

更新:这就是我想要完成的事情

# Default values
FullDate = now().format("yyyy-MM-dd_HH:mm:ss")
Name = "John"
ElementID = "Apple"
ElementCD = "01Appxz"
Year = now().format("yyyy")
Day = now().format("dd")
Month = now().format("MM")
############################

String = "{FullDate}_{Month}_{Day}_{Year}_{ElementID}_{ElementCD}"
String_split = String.split("_")

for params in range(len(String_split)):

    if "FullDate" in String_split[params]:
        Report_Name = Report_Name + FullDate + "_"
    elif "Name" in String_split[params]:
        Report_Name = Report_Name + Name + "_"
    elif "ElementID" in String_split[params]:
        Report_Name = Report_Name + ElementID + "_"
    elif "ElementCD" in String_split[params]:
        Report_Name = Report_Name + ElementCD + "_"
    elif "Year" in String_split[params]:
        Report_Name = Report_Name + Year + "_"
    elif "Day" in String_split[params]:
        Report_Name = Report_Name + Day + "_"
    elif "Month" in String_split[params]:
        Report_Name = Report_Name + Month + "_"

# Report_Name must return default values, ordered by String variable (eg: FullDate, 1st position; Month 2nd position etc..)
# >> "1999-01-01_10:10:29_01_01_1999_Apple_01Appxz"
# if the String variable changes the params order to
# String = "{Year}_{Month}_{ElementCD}_{FullDate}_{ElementID}_{Day}"
# Report_Name should return
# >> "1999_01_01Appxz_1999-01-01_10:10:29_Apple_01"

【问题讨论】:

  • 一般来说,您的方法是可以的(Python 没有switch/case 语句,因此使用if/elifif/if 链是完全pythonic)。如果您的 do something 语句非常相似(例如,始终具有不同参数的相同函数),那么您可以使用字典进行切换,但可读性可能会受到影响。
  • 我会说for param in String_split: 作为首发。但取决于“做某事”的含义,可能还有更多的优化空间。
  • 优化可能有,但你的方法没问题。
  • 从整体上阅读这个问题让我相信这是一个 XY 问题。你到底想达到什么目的?如果您要做的只是用任意变量格式化字符串,那么还有更好的方法。
  • 如果您有工作代码想在可读性、可维护性、兼容性和/或速度等主题上进行改进,请联系Code Review。跨度>

标签: python string for-loop replace split


【解决方案1】:
  • 使用for name in names 消除所有String_split[params] 噪音。
  • 从变量中删除{},以便您可以使用== 而不是in
  • 使用+=

这得到:

names = "FullDate Month Day Year ElementID ElementCD".split()
for name in names:
    if "FullDate" == name:
        Report_Name += FullDate + "_"
    elif "Name" == name:
        Report_Name += Name + "_"
    elif "ElementID" == name:
        Report_Name += ElementID + "_"
    elif "ElementCD" == name:
        Report_Name += ElementCD + "_"
    elif "Year" == name:
        Report_Name += Year + "_"
    elif "Day" == name:
        Report_Name += Day + "_"
    elif "Month" == name:
        Report_Name += Month + "_"

您还应该学习如何使用格式字符串和** 运算符。如果您将 FullDate 内容更改为字典,则可以使用:

REPORT_FORMAT = '{FullDate}_{Month}_{Day}_{Year}_{ElementID}_{ElementCD}'

report = {
    'FullDate': now().format("yyyy-MM-dd_HH:mm:ss")
    'Name': "John"
    'ElementID': "Apple"
    'ElementCD': "01Appxz"
    'Year': now().format("yyyy")
    'Day': now().format("dd")
    'Month': now().format("MM")
}
report_name = REPORT_FORMAT.format(**report)

【讨论】:

    【解决方案2】:

    阅读前
    - 正如你提到的,这是一个不使用字典的解决方案


    解决方案

    与:

    #Default values
    FullDate = '2010-01-01_00:00:00'
    Name = "John"
    ElementID = "Apple"
    ElementCD = "01Appxz"
    Year = '2010'
    Day = '01'
    Month = '01'
    #--
    
    String = "{FullDate}_{Month}_{Day}_{Year}_{ElementID}_{ElementCD}"
    

    您可以在没有for 循环的情况下执行此操作,只需根据需要进行替换:

    Report_Name = '.RName_' + String
    if "FullDate" in Report_Name:
        Report_Name = Report_Name.replace('{FullDate}',FullDate)
    if "Name" in Report_Name:
        Report_Name = Report_Name.replace('{Name}',Name)
    #...
    if "ElementCD" in Report_Name:
        Report_Name = Report_Name.replace('{ElementCD}',ElementCD)
    
    print(Report_Name)
    .RName_2010-01-01_00:00:00_..._01Appxz
    

    [小心]另一种解决方案

    或者您可以使用.eval()(请参阅documentation)根据变量的名称来评估变量。它要求parametersvariables 名称相同。
    这是一种方法:

    import re
    Parameters = [re.sub('[{-}]+', '', s) for s in String.split('_')]
    
    Report_Name = '.RName_' + String
    for p in Parameters:
        Report_Name = Report_Name.replace('{%s}'%p,eval(p))
    
    print(Report_Name)
    .RName_2010-01-01_00:00:00_01_01_2010_Apple_01Appxz
    

    注意你应该使用.eval() 小心 - see Why is using eval a bad practice
    检查此解决方案的替代方案 - 例如using globals/locals/vars - 如果:

    • 您想要类似的行为
    • 您认为它对您的问题不够安全

    【讨论】:

      猜你喜欢
      • 2020-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-12
      • 2016-02-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多