1

I'm trying to add Link argument to ini file by using python. Example of ini file:

[sometag]
sometext
sometext
sometext

[sometag2]
sometext2
sometext2
sometext2

[sometag3]
sometext3
sometext3
sometext3

I need to do like this:

[sometag]
sometext
sometext
sometext

Link = [sometag]

[sometag2]
sometext2
sometext2
sometext2

Link = [sometag2]
...

My for loop:

for i in range(len(m)):
    if m[i] in t:
        for j in xrange(i, len(m)):
            if len(m[j].strip()) == 0 and m[j+1].startswith('['):
                m.insert(j, Link.....
                break


# m = ini_file.readlines()
# t = ['[sometag]', '[sometag2]']

My code works, but it does not add Link for last tags. I've found why. If I add in range(len(m)+100): Then code adds all Links.

Looks like len(m) is old value (static?), because I'm increasing len with insert during loop. Any ideas?

I have tried something like insertings = 0, then range(len(m)+insertings) and afer insert insertings = insertings+1 But no luck :(

3
  • If it is a small .ini file why not creating a new and then renaming the file? len(m) yes it won't change over time and your list will become inconsistent. Commented Mar 11, 2020 at 18:22
  • @mad_ thanks for reply. It is not small ini file :( Commented Mar 11, 2020 at 18:24
  • I have a new idea. I can count lines before loop, right? current lines count + len of t * 3 Commented Mar 11, 2020 at 18:25

2 Answers 2

1

Create a new list:

new = []
tag = None
for line in m:
    if line.startswith('['):
        if tag:
            new.append('Link = ' + tag)
        tag = line
    new.append(line)
Sign up to request clarification or add additional context in comments.

Comments

1

Using range locks you to a specific number of iterations; range(len(m)) constructs a range using the value of len(m) now, and it's never changed (it can't be ranges are immutable). You want this behavior, in the same way you want:

s = '123'
i = int(s)
s = 'abc'

to leave i with the value 123, rather than dying when int's argument retroactively becomes 'abc' (allowing range(len(m))'s behavior to retroactively change as m changes would be morally equivalent, and equally insane).

Modifying a list while iterating over it is frowned upon, especially if you're inserting before the end of the list, or deleting elements. It's just too error-prone; in this case, when j takes the initial value of i, and an insert occurs, you've inserted a value that the loops will never see (because it will look at i + 1 next), while inserting it at j > i will be seen by the outer loop, but not the inner (and in both cases, the value of m[j] will get processed twice, on consecutive loops).

Generally, the safer solution is to build a new list from scratch, adding the elements from the existing list as needed, and new elements to the end as you go. It's also much faster inserting to the middle of a list is O(n) for each insert (overall cost O(m * n) where m is number of insertions required, n is input size), while append is amortized O(1) (overall cost O(m + n)).

Comments

Your Answer

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.