1

I am having a problem that I just don't know how to solve and nothing I'm finding is helping. My problem is that I have a list of names (strings), in this list I will have the same name show up more than once.

lst = ['hello.com', 'hello.com', 'hello.com', 'world.com', 'test1.com']
index = web_lst.index(domain)+1
print(index)

The issue with this code is that index() will always find and use the first 'hello.com' instead of any of the other "hello.com's", so index will always be 1. If I were asking for any of the other names then it'd work I think.

I am trying to get the integer representation of the 'hello.com' names (1, 2, 3, etc.), and I don't know how to do that or what else to use besides python lists. This, I don't think is going to work and I'm asking for any other ideas on what to do or use instead of using a list. (if what I'm trying to do is not possible with lists)



My main goal is basically a login manager using sqlite3 and I want to have the ability to have multiple logins with some having the same domain name (but with different data and notes, etc.), because we like to have multiple logins/accounts for 1 website. I have a TUI (beaupy) for selecting the domain/option you want to get the login for but if you have more than 1 of the same domain name it doesn't know which one to pick. I have managed to use integers as IDs in the sqlite3 database to help but the main issue is the picking of an element from a list to get a number, to then plug into the read() function. So the list options will correlate to the "IDs" in the database. List index 0+1 would be option/row 1 in the database (and so on).

def clear():
    os.system('clear||cls')


def add(encrypted_data):
    ID = 1
    database = sqlite3.connect('vault.gter')
    c = database.cursor()

    #Check to see if IDs exist and if yes then get how many/length of list and add 1 and use that instead.
    c.execute("SELECT id FROM logins")
    all_ids = c.fetchall()
    out = list(itertools.chain(*all_ids))
    list_length = len(out)
    if not all_ids:
        pass
    else:
        for x in out:
            if x == list_length:
                ID = x+1
            else:
                pass

    c.execute(f"INSERT INTO logins VALUES ('{ID}', '{encrypted_data}')")
    database.commit()
    database.close()




def domains(dKey):
    database = sqlite3.connect('vault.gter')
    c = database.cursor()
    c.execute("SELECT data FROM logins")
    websites = c.fetchall()
    enc_output = list(itertools.chain(*websites))

    web_lst = []
    note_lst = []
    for x in enc_output:
        result = gcm.stringD(x, dKey) #decrypt encrypted json string.
        obj_result = json.loads(result) #turns back into json object
        website = obj_result['Domain']
        notes = obj_result['Notes']
        web_lst.append(website)
        note_lst.append(notes)

    for w,n in zip(web_lst, note_lst):
        with open('.lst', 'a') as fa:
            fa.writelines(f"{w}  ({n})\n")
            fa.close()


    with open(".lst", "r+") as fr:
        data = fr.read()
        fnlst = data.strip().split('\n')
        fr.truncate(0)
        fr.close()

    os.remove(".lst")
    print(f'(Press "ctrl+c" to exit)\n-----------------------------------------------------------\n\nWebsite domain/name to get login for?\n')
    domain = beaupy.select(fnlst, cursor_style="#ffa533")

    clear()
    if domain == None:
        clear()
        return
    else:
        domain = domain.split(' ', 1)[0] #get first word in a string.
        print(domain) #debug
        index = web_lst.index(domain)+1
        input(index) #debug

        pwd = read(index)
        return pwd




# Come up with new way to show available options to chose from and then get number from that to use here for "db_row".
def read(db_row):
    database = sqlite3.connect('vault.gter')
    c = database.cursor()

    c.execute("SELECT id FROM logins")
    all_ids = c.fetchall()
    lst_output = list(itertools.chain(*all_ids))

    if not all_ids:
        input("No IDS") #debug
        database.commit()
        database.close()
        return
    else:
        for x in lst_output:
            if x == db_row:
                c.execute(f"SELECT data FROM logins WHERE id LIKE '{db_row}'") #to prevent my main issue of it not knowing what I want when two domain names are the same.
                stoof = c.fetchone()
                database.commit()
                database.close()
                return stoof[0]
            else:
                #(debug) - input(f"error, x is not the same as db_row. x = {x} & db_row = {db_row}")
                pass


If anyone has a better way of doing this whole login manager thing, I'll be very very appreciative. From handling the database and sqlite3 commands, better IDs? to perhaps completely a different (and free) way of storage. And finding a better way to handle my main problem here (with or without having to use lists). Anything is helpful. <3

If anyone has questions then feel free to ask away and I'll respond when I can with the best of my knowledge.

Ori
  • 31
  • 8

2 Answers2

0

You can get both the index and the element using a for-loop.

for i in range(len(lst)):
    element = lst[i]
    if element == domain:
        print(i)

This should give you all indexes of domain.

Edited Code:

d = {}
c = 0
for i in range(len(lst)):
    element = lst[i]
    if element == domain:
        c += 1
        d[c] = i

for number, index in d.items():
    # Do something here. Remember to use number and index instead of c and i!

c is the occurence number, and i is the index.

  • 1
    Although this does show me at what positions 'hello.com' occurs in `web_lst`...I don't have a way to know which one of the 3 was the one that has been chosen. Like, say I chose the `hello.com` in position 2 and not 0 or 1..I want to use 2 to pass into `read()`. – Ori Dec 03 '22 at 00:41
  • You can add a counter variable `c` and a dictionary `d` and define them before the for loop. Inside the if-statement, there will be `c += 1` and `d[c] = i`. – ApplesAndCode464 Dec 03 '22 at 00:58
  • So something like this? `c = 0` `d = {}` before the for loop.? I'm not sure I'm quite following. – Ori Dec 03 '22 at 01:03
  • @Ori I editted the OP. I hope this helps. – ApplesAndCode464 Dec 03 '22 at 01:07
  • I appreciate the help but nothing I am trying is giving me what I want. `d[c]` keeps giving me the first `hello.com` in the list or the last `hello.com` in the list (depending on if I call `read()` in or outside of the for loop. and I can never get the right number. Unless it is anything else but one of the `hello.com`'s. Do you have anything else that could help with this small issue. I am so close with this to being the answer I think? – Ori Dec 03 '22 at 02:23
  • I think that I see the problem. You also need to do an iteration of the dictionary: `for number, index in d.items(): ...` and place the `read()` inside the for loop. Use `number` and `index` instead of `c` and `i`. – ApplesAndCode464 Dec 03 '22 at 03:54
  • Okay, I'll give it a try and tinker with things. I would like you (if you don't mind) to update your answer post to reflect these changes as in the case of this actually working and this is the answer, I want it to be right there for others to see when I mark it as "The answer", etc. I also am unsure as to where exactly I need to do this iteration, if I make a new for loop under the already existing for loop, do I edit the already existing for loop to replace variables, etc. I'm sure I could eventually figure it out after hours of brute forcing it but yeah. I'll let you know if it works. – Ori Dec 03 '22 at 06:21
  • Okay, good luck on your project, @Ori! – ApplesAndCode464 Dec 03 '22 at 09:01
  • Yeah, I've been trying for a couple hours now and I don't know what to do with `index` and `number`. Nothing I'm doing is giving me the right position I want for whatever `hello.com` I choose. Just the first `hello.com` it sees. (no matter which one I chose). I've tried to replicate what I've seen in the first loop in this new for loop using `name` and `index` instead but that doesn't seem to be working. Idk. If you can, just post your full answer so this can end and come to a conclusion other than hours of confusion/puzzle solving. And once again, Thank you for your help! – Ori Dec 03 '22 at 16:13
  • @Ori can you show me your code in the for loop? For clarification, `index` is the position inside the list, and `number` says whether it is the first, second, third, etc... occurence. – ApplesAndCode464 Dec 03 '22 at 23:27
  • Code: `https://pastebin.com/gPaBDF73` (expires in 24hrs from now). This shows my domains() function. The issue is that I don't know what to do in the 2nd for loop you mentioned. The iteration one using `index` and `number`. I don't know how to use them to achieve my goal. – Ori Dec 04 '22 at 01:26
  • I am not sure what you can do with the `number`, but in the OP, it seems like you should have `pwd = read(index)` followed by `return pwd`. However, this only gives the first occurence. You can add an if statement to check whether `number` is the occurence that you want. – ApplesAndCode464 Dec 04 '22 at 23:01
0

Here is a one-liner:

[{item:[i for i, x in enumerate(lst) if x == item]} for item in set(lst)]
Vitali Avagyan
  • 1,193
  • 1
  • 7
  • 17
  • This doesn't tell me which `hello.com` was chosen or what any option was chosen, just where everything occurs in the list/at what position. And that doesn't help when I need to know if `hello.com` at index 0 was chosen? or was the `hello.com` at index 1 chosen?, etc... – Ori Dec 03 '22 at 17:02