2

I have a list of 9 lists, inside every lists there are few elements. Every elements are string. Now I want to create another list of lists based upon partially similar string. I can do that individually, without using conditional statement. But I want to do it using if condition.

What I have tried :

var = ["pr", "tas", "ts"]

prs = []
for i in all_files:
    for j in i:
        if var[0] in j:
            prs.append(j)
            
tass = []
for i in all_files:
    for j in i:
        if var[1] in j:
            tass.append(j)
            
tss = []
for i in all_files:
    for j in i:
        if var[2] in j:
            tss.append(j)

In the above way I can do that thing. But I want to loop over var as well. For that I have tried :

gg = []            
for i in all_files:
    for j in i:
        for k in var[0:3]:
            kk = []
            if k in j:
                kk.append(j)
        gg.append(kk)

It is giving a list, but there are so many blank lists inside that list. I want all the "pr" containing file would be in a list, same for "ts" and "tas" and they will be inside a list. Please let me know if anyone have any doubt Thank you.

  • If you don't want empty `kk` lists to be appended to `gg`, check if `kk` is empty before you append it to `gg` – Pranav Hosangadi Aug 22 '23 at 18:50
  • To clarify: you have three "condititions", `"pr"`, `"tas"`, and `"ts"`, and you want to sort an iterable of `all_files` into three separate lists based on whether or not the file (presumably, rather the file **name**) contains one of those three strings? – JRiggles Aug 22 '23 at 18:50
  • You are correct. Let me give you a little bit more insight. all_files contains 9 list, each list have file names contain those three strings "pr", "tas", and "ts". Please let me know it it clarifies or not. Thanks @JRiggles – SWARNENDU PAL Aug 22 '23 at 18:54
  • In the interest of clarity and providing a complete [mre], you should include sample input data in your question. I added some sample data to my answer based on your comment above, but in the future please add this when you ask the question. – Pranav Hosangadi Aug 22 '23 at 19:00
  • This is essentially a ["variable variables" question](https://stackoverflow.com/q/1373164/984421), with the answer being to use a `dict`. Thus, in your second example, do `gg = {k: [] for k in var}` and then `if k in j: gg[k].append(j)`. This will give the same result as your first example, except that e.g. the variable `prs` becomes `gg['prs']`. This should be a lot easier to work with than having lots of separate variables (and you can also easily get a list of lists with `list(gg.values())`). – ekhumoro Aug 22 '23 at 19:36
  • sorry for the inconvenience caused by me @PranavHosangadi – SWARNENDU PAL Aug 23 '23 at 05:59
  • You suggestion worked @ekhumoro. I did a little bit of modification as I need list, so the code that I have used as follows : ```lang-py gg = [[] for k in var] for i in all_files: for j in i: for k in var: if k in j: gg[var.index(k)].append(j) ``` – SWARNENDU PAL Aug 23 '23 at 06:52
  • @SWARNENDUPAL no inconvenience at all! FWIW, you shouldn't do `var.index(k)` because that's an extra loop hidden in the `.index` call. You already know the index of the iteration because you're the one doing the iteration, so use `enumerate` to get the index. At the end of the day you're trying to get the same index from `gg` as you are from `k`, so you might as well iterate over `zip(gg, k)`, which is what my code does. – Pranav Hosangadi Aug 30 '23 at 03:25

2 Answers2

0

First, make a list out that contains one empty list for each element of var

var = ["pr", "tas", "ts"]
out = [[] for _ in var] 

This is equivalent to creating the three empty lists prs, tass, and tss.

Then, when you iterate over var, also iterate over out, and append to that element of out.

for i in all_files:
    for j in i:
        for o, k in zip(out, var):
            if k in j:
                o.append(j)

In the for o, k... loop, when k is "pr", o is the first list in out (prs in your old approach). When k is "tas", o is the second list in out (tass in your old approach).

Trying this with some sample data:

all_files = [["pr0", "tas0", "ts0", "abc0"],
             ["pr10", "tas10", "ts10", "abc10"],
             ["pr20", "tas20", "ts20", "abc20"]] 

gives:

out = [['pr0', 'pr10', 'pr20'], ['tas0', 'tas10', 'tas20'], ['ts0', 'ts10', 'ts20']]

The first element contains all the pr values, the second element contains all the tas values, etc.

You can unpack the out list into your separate variables if you really want:

prs, tass, tss = out

which gives:

prs = ['pr0', 'pr10', 'pr20']

tass = ['tas0', 'tas10', 'tas20']

tss = ['ts0', 'ts10', 'ts20']
Pranav Hosangadi
  • 23,755
  • 7
  • 44
  • 70
0

Although you should be using a dictionary for this instead of individual variables, you could combine the 3 loops using a list of variables that you pair up with the list of string patterns using zip():

prs, tass, tss = [], [], []      # individual variables (lists)
varList = [prs, tass, tss]       # list of variables
var     = ["pr", "tas", "ts"]    # corresponding string patterns

for aFile in all_files:                           # loop through files
    for line in aFile:                            # lines of each file
        for aList, pattern in zip(varList,var):   # variables and patterns
            if pattern in line:
                aList.append(line)                # tally matches

If you decide to use a dictionary, the loops could look like this:

patterns = {"prs":"pr", "tass":"ts", "tss":"ts"}
matches  = {k:[] for k in patterns}
for aFile in all_files:
    for line in aFile:
        for name,pattern in patterns.items():
            if pattern in line:
                matches[name].append(line)

You can then access individual lists using their name as a string: matches['prs']

If you find the brackets and quotes too cumbersome, you can create a special dictionary class of your own that allows more streamlined referencing:

class VarDict(dict): __getattr__ = dict.get

And use it for your matches:

matches  = VarDict({k:[] for k in patterns})

And then you can reference the matches more directly: matches.prs

Alain T.
  • 40,517
  • 4
  • 31
  • 51