简体   繁体   中英

Can you use a List Comprehension when not appending the iterable

So I decided to start using List Comprehensions and after a little bit of googling I managed to do this:

# old way
loaded_sounds = []
for i in assetList_text:
    if i.startswith("loaded_sound"):
        loaded_sounds.append(i.split(',')[1])

# new way
loaded_sounds = [i.split(',')[1] for i in assetList_text if i.startswith("loaded_sound")]

Which works perfectly. So I thought id continue on to the hard for loops and this is where the list comprehension result isn't matching the for loop result.

So this conversion is a little harder as it not only has 2 'if' statment's but its not actually appending the index either.

gsc_files = []
for i in assetList_text:
    if ".gsc" in i:
        d = i.split(',')[-1].replace("\n", "")
        if d not in gsc_files:
            gsc_files.append(d)

So this prints out: 6 But with this:

gsc_files = [i.split(',')[-1].replace("\n", "") for i in assetList_text if ".gsc" in i if i.split(',')[-1].replace("\n", "") not in gsc_files]

It prints out: 0 So I don't know where its going wrong?

Also whilst on the topic of List Comprehensions id like to know their vastness. Could the following 2 for loops be converted to list comprehensions?

[1]

weapon_files = []
x = join(f"{WAW_ROOT_DIR}/raw/weapons/sp")
for path, subdirs, files in walk(x):
    for fileName in files:
    content = join(x, fileName)
    if content not in weapon_files:
        weapon_files.append(f"{WAW_ROOT_DIR}/raw/weapons/sp/{fileName}")

[2]

gsc_files_dir = []
for path in gsc_files:
if f"{CURRENT_SELECTED_MOD.lower()}" in path:
    dir = join(f"{WAW_ROOT_DIR}/mods/{CURRENT_SELECTED_MOD}/{path}")
    gsc_files_dir.append(dir)
elif os.path.exists(f"{WAW_ROOT_DIR}/mods/{CURRENT_SELECTED_MOD}/{path}"):
    dir = join(f"{WAW_ROOT_DIR}/mods/{CURRENT_SELECTED_MOD}/{path}")
    gsc_files_dir.append(dir)
else:
    dir = join(f"{WAW_ROOT_DIR}/raw/{path}")
    gsc_files_dir.append(dir)

Regards, Phil

EDIT: in response to "DialFrost's" question:

f1 = join(f"{WAW_ROOT_DIR}/zone_source/english/assetlist/{CURRENT_SELECTED_MOD}.csv")
f2 = join(f"{WAW_ROOT_DIR}/zone_source/english/assetlist/{CURRENT_SELECTED_MOD}_patch.csv")
f3 = join(f"{WAW_ROOT_DIR}/zone_source/english/assetinfo/{CURRENT_SELECTED_MOD}.csv")
f4 = join(f"{WAW_ROOT_DIR}/zone_source/english/assetinfo/{CURRENT_SELECTED_MOD}_patch.csv")

with open(f1, 'r') as assetList, open(f2, 'r') as assetListPatch, open(f3, 'r') as assetInfo, open(f4, 'r') as assetInfoPatch:
    assetList_text = assetList.readlines()
    assetListPatch_text = assetListPatch.readlines()
    assetInfo_text = assetInfo.readlines()
    assetInfoPatch_text = assetInfoPatch.readlines()

assetList_text is a large(3k+ lines) file. So here's some info from assetList_text including the ".gsc" lines:

fx,weapon/shellejects/fx_smk_weapon_shell_eject
fx,weapon/shellejects/fx_smk_weapon_shell_emit
fx,weapon/shellejects/shotgun
fx,weapon/shellejects/shotgun_resting
fx,weapon/shellejects/shotgun_view
fx,weapon/shellejects/shotgun_view_blurred01
mptype,nazi_zombie_heroes
character,char_zomb_player_0
character,char_zomb_player_1
character,char_zomb_player_2
character,char_zomb_player_3
rawfile,animtrees/zombie_factory.atr
rawfile,clientscripts/_zombie_mode.csc
rawfile,clientscripts/createfx/dlc3_fx.csc
rawfile,clientscripts/createfx/free_city_fx.csc
rawfile,clientscripts/dlc3_code.csc
rawfile,clientscripts/dlc3_teleporter.csc
rawfile,clientscripts/free_city.csc
rawfile,clientscripts/free_city_amb.csc
rawfile,maps/createart/free_city_art.gsc
rawfile,maps/createfx/dlc3_fx.gsc
rawfile,maps/createfx/free_city_fx.gsc
rawfile,maps/dlc3_code.gsc
rawfile,maps/dlc3_teleporter.gsc
rawfile,maps/free_city.gsc
rawfile,rumble/flamethrower
rawfile,rumble/flamethrower_h.rmb
rawfile,rumble/flamethrower_l.rmb
rawfile,vision/zombie_factory.vision

Try replace two if statements to one, and add 'and' operator instead of second 'if'. Because I'm not sure what 2 'if' works fine in list-comprehension. So, change this:

gsc_files = [i.split(',')[-1].replace("\n", "") for i in assetList_text if ".gsc" in i if i.split(',')[-1].replace("\n", "") not in gsc_files]

To this:

gsc_files = [i.split(',')[-1].replace("\n", "") for i in assetList_text if (".gsc" in i) and (i.split(',')[-1].replace("\n", "") not in gsc_files)]

'add' operator should compare correct two statements

And I'm not sure what try convert all for loops or just large parts of code in list-comprehension it is good idea, because this can make your code hard to read

[1] First for loop you mentioned!

weapon_files = []
x = join(f"{WAW_ROOT_DIR}/raw/weapons/sp")
for path, subdirs, files in walk(x):
    for fileName in files:
    content = join(x, fileName)
    if content not in weapon_files:
        weapon_files.append(f"{WAW_ROOT_DIR}/raw/weapons/sp/{fileName}")

Answer: Hope it would help! At first, you are trying to access a list which is not created before the list comprehension starts. For your case, you try to create an empty list at first weapon_files = [] , again list comprehension creates a new list weapon_files , but this time, we assign the list with the data that we need to append using := operator. Refer https://docs.python.org/3/whatsnew/3.8.html#assignment-expressions . Now everytime recursively list gets updated for the condition.

weapon_files = []
weapon_files = [weapon_files := f"{WAW_ROOT_DIR}/raw/weapons/sp/{fileName}" for path, subdirs, files in walk(x)  for fileName in files if join(x, fileName) not in weapon_files]

[2] Second 'for loop' mentioned!

gsc_files_dir = []
for path in gsc_files:
if f"{CURRENT_SELECTED_MOD.lower()}" in path:
    #condition 1 ref variable to append ==> var1
    dir = join(f"{WAW_ROOT_DIR}/mods/{CURRENT_SELECTED_MOD}/{path}")
    gsc_files_dir.append(dir)
elif os.path.exists(f"{WAW_ROOT_DIR}/mods/{CURRENT_SELECTED_MOD}/{path}"):
    #condition 2 ref variable to append ==> var2
    dir = join(f"{WAW_ROOT_DIR}/mods/{CURRENT_SELECTED_MOD}/{path}")
    gsc_files_dir.append(dir)
else:
    #condition 3 ref variable to append ==> var3
    dir = join(f"{WAW_ROOT_DIR}/raw/{path}")
    gsc_files_dir.append(dir)

Answer: Trying list comprehension for this loop statement doesn't bring better readability but still, we can apply. I've shown the template answer using the above commented ref variable names.(var1, var2, var3).

gsc_files_dir = [var1 if f"{CURRENT_SELECTED_MOD.lower()}" in path else var2 if os.path.exists(f"{WAW_ROOT_DIR}/mods/{CURRENT_SELECTED_MOD}/{path}") else var3 for path in gsc_files]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM