-1

I've got a simple list "passage" that contains strings. Goal is to join these split words into lines of 5 words each. Using modulus 5 (against index value + 1 to simplify) as test of when to add a newline character.

For reasons that escape me, it works fine, except when it suddenly decides to skip a multiple of 5. I can't make out why it is inconsistent. Mysteriously skips indices 40, 45, and 55.

for word in passage:
    indx = passage.index(word)   # dump into variable "indx" for convenience
    if (indx+1) %5  == 0:        # act every 5th element of list
        passage[indx] = f"{word}\n{indx+1}" # add line break and index number to element

print(passage)
print()

final = " ".join(passage)
print(final)

Altered list output:

['When', 'in', 'the', 'Course', 'of\n5', 'human', 'events,', 'it', 'becomes', 'necessary\n10', 'for', 'one', 'people', 'to', 'dissolve\n15', 'the', 'political', 'bands', 'which', 'have\n20', 'connected', 'them', 'with', 'another,', 'and\n25', 'to', 'assume', 'among', 'the', 'powers\n30', 'of', 'the', 'earth,', 'the', 'separate\n35', 'and', 'equal', 'station', 'to', 'which', 'the', 'Laws', 'of', 'Nature', 'and', 'of', "Nature's", 'God', 'entitle', 'them,\n50', 'a', 'decent', 'respect', 'to', 'the', 'opinions', 'of', 'mankind', 'requires', 'that\n60', 'they', 'should', 'declare', 'the', 'causes\n65', 'which', 'impel', 'them', 'to', 'the', 'separation.']

and "joined" output as string:

When in the Course of
5 human events, it becomes necessary
10 for one people to dissolve
15 the political bands which have
20 connected them with another, and
25 to assume among the powers
30 of the earth, the separate
35 and equal station to which the Laws of Nature and of Nature's God entitle them,
50 a decent respect to the opinions of mankind requires that
60 they should declare the causes
65 which impel them to the separation.

Thoughts?

Sorry not to have included the original list, ewong:

['When', 'in', 'the', 'Course', 'of', 'human', 'events,', 'it', 'becomes', 'necessary', 'for', 'one', 'people', 'to', 'dissolve', 'the', 'political', 'bands', 'which', 'have', 'connected', 'them', 'with', 'another,', 'and', 'to', 'assume', 'among', 'the', 'powers', 'of', 'the', 'earth,', 'the', 'separate', 'and', 'equal', 'station', 'to', 'which', 'the', 'Laws', 'of', 'Nature', 'and', 'of', "Nature's", 'God', 'entitle', 'them,', 'a', 'decent', 'respect', 'to', 'the', 'opinions', 'of', 'mankind', 'requires', 'that', 'they', 'should', 'declare', 'the', 'causes', 'which', 'impel', 'them', 'to', 'the', 'separation.']

I'll check out enumerate. (Just getting started with Python. Sorry if I seem obtuse.)

Eduardo Reis, thanks for the suggestion that duplicate array elements cause some sort of index problem. I'll investigate.

  • 1
    Welcome to Stack Overflow. What is your sample input? – ewokx Jun 10 '22 at 01:07
  • 3
    Writing `print(indx, word)` would've been faster than writing this question. – Kelly Bundy Jun 10 '22 at 01:11
  • 1
    `index` is essentially always the wrong tool. Use `enumerate`. – user2357112 Jun 10 '22 at 01:12
  • Use `for indx, word in enumerate(passage):`. Notice that, in your case, if `word` repeats in passage you will get the wrong result – Eduardo Reis Jun 10 '22 at 01:12
  • Welcome to Stack Overflow. The problem occurs because `.index` finds *the first* index of the given word in the list. It cannot possibly give you the index of "the current word", because you are *calling a method*; it does not have the context of the loop, it only sees the *word*, which it then looks up within the list. The solution is to use a looping construct that *gives you the index while looping*, as in the first linked duplicate. – Karl Knechtel Jun 10 '22 at 01:48
  • Alternately, you can try a different approach to the problem: directly split the list into sub-lists of 5, using technique from the second linked duplicate, and then label lines as needed. – Karl Knechtel Jun 10 '22 at 01:48
  • Also: please follow the [tour] and read [ask], and note well that this is **not a discussion forum**. Do not edit the question to "reply" to comments; instead, edit it to *fix issues* raised in the comments. Finally, in the future, try to figure out problems yourself first, using [these](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) techniques. – Karl Knechtel Jun 10 '22 at 01:50

1 Answers1

1

You can just split the passage into words (on whitespace) and then chunk that list of words into blocks of 5, joining each chunk with the index (if > 0):

passage = """
When in the Course of human events, it becomes necessary
for one people to dissolve the political bands which have
connected them with another, and to assume among the powers 
of the earth, the separate and equal station to which the 
Laws of Nature and of Nature's God entitle them, a decent 
respect to the opinions of mankind requires that they should 
declare the causes which impel them to the separation.
"""
words = passage.split()
chunks = [' '.join(([str(i)] if i else []) + words[i:i+5]) for i in range(0, len(words), 5)]

Output:

[
 'When in the Course of',
 '5 human events, it becomes necessary',
 '10 for one people to dissolve',
 '15 the political bands which have',
 '20 connected them with another, and',
 '25 to assume among the powers',
 '30 of the earth, the separate',
 '35 and equal station to which',
 '40 the Laws of Nature and',
 "45 of Nature's God entitle them,",
 '50 a decent respect to the',
 '55 opinions of mankind requires that',
 '60 they should declare the causes',
 '65 which impel them to the',
 '70 separation.'
]

This can then be joined with \n to get the output:

print('\n'.join(chunks))

Output:

When in the Course of
5 human events, it becomes necessary
10 for one people to dissolve
15 the political bands which have
20 connected them with another, and
25 to assume among the powers
30 of the earth, the separate
35 and equal station to which
40 the Laws of Nature and
45 of Nature's God entitle them,
50 a decent respect to the
55 opinions of mankind requires that
60 they should declare the causes
65 which impel them to the
70 separation.
Nick
  • 138,499
  • 22
  • 57
  • 95