0

I am developing a program that identifies individual words in a sentence, stores these in a list and replaces each word in the original sentence with the position of that word in the list, so the sentence can be recreated from the positions of these words in this list using the sequence 1,2,3,4,5,6,7,8,9,1,3,9,6,7,8,4,5. My code so far is below but I need some advice on how to make it more efficient and shorter:

import time

sentence = "ASK NOT WHAT YOUR COUNTRY CAN DO FOR YOU ASK WHAT YOU CAN DO FOR YOUR COUNTRY"
s = sentence.split() 
another = [0]
time.sleep(0.5)
print(sentence)
for count, i in enumerate(s): 
    if s.count(i) < 2:
        another.append(max(another) + 1)
    else:
        another.append(s.index(i) +1)
another.remove(0)
time.sleep(0.5)
print(another)
Tony Babarino
  • 3,355
  • 4
  • 32
  • 44
  • 2
    If this is **working code** that you think could be improved, see [codereview.se]. If not, please clarify the issue with a [mcve]. – jonrsharpe Apr 20 '16 at 20:37
  • 2
    Well, if you lose the time.sleep calls, the code will be a second faster and two lines shorter. – zmbq Apr 20 '16 at 20:41
  • I know, I just want to make it more efficient as my friend managed to get the same result by using 4 lines of code –  Apr 20 '16 at 20:45
  • 1
    @MrPython less lines (by itself) doesn't make the code more efficient or readable. – jfs Apr 20 '16 at 21:11

4 Answers4

2

Here's a linear algorithm:

position = {} # word -> position
words = sentence.split()
for word in words:
    if word not in position: # new word
       position[word] = len(position) + 1 # store its position
print(*map(position.__getitem__, words), sep=",")
# -> 1,2,3,4,5,6,7,8,9,1,3,9,6,7,8,4,5

The print() call uses Python 3 * syntax to unpack the result returned by map() that returns positions for the corresponding words here. See What does ** (double star) and * (star) do for parameters?

Community
  • 1
  • 1
jfs
  • 399,953
  • 195
  • 994
  • 1,670
1

To get a list of word positions in sentence and recreate the original sentence from this list:

sentence = "ASK NOT WHAT YOUR COUNTRY CAN DO FOR YOU ASK WHAT YOU CAN DO FOR YOUR COUNTRY"
s = sentence.split()
positions = [s.index(x)+1 for x in s]
recreated = [s[i-1] for i in positions]
# the reconstructed sentence
print(" ".join(recreated))
# the list of index numbers/word positions
print(positions)
# the positions as a space separated string of numbers
print(" ".join(positions)

Lists are zero-indexed so the first element is index 0, not 1. You could, of course, add 1 to all indices in the list comprehension if you wanted it to start at 1.

To get exactly the same output as your script produces:

sentence = "ASK NOT WHAT YOUR COUNTRY CAN DO FOR YOU ASK WHAT YOU CAN DO FOR YOUR COUNTRY"
s = sentence.split()
positions = [s.index(x)+1 for x in s]
print(sentence)
print(positions)

Output:

ASK NOT WHAT YOUR COUNTRY CAN DO FOR YOU ASK WHAT YOU CAN DO FOR YOUR COUNTRY
[1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 3, 9, 6, 7, 8, 4, 5]
jDo
  • 3,962
  • 1
  • 11
  • 30
  • While technically not required, you might want to dedupe s by doing something like ``list(set(sentence.split()))`` Might be relevant if the corpus of words gets large and so a lot of ``s.index()`` calls are made. – nephlm Apr 20 '16 at 21:06
  • 1
    But this doesn't print the numbers as the end result it only prints the sentence –  Apr 20 '16 at 21:11
  • @MrPython `print (positions)` or `print(" ".join(positions)`. I just thought re-constructing the sentence from the positions was the end goal – jDo Apr 20 '16 at 21:13
  • Yes now it prints out the numbers but it starts at 0. I want the result to be this 1,2,3,4,5,6,7,8,9,1,3,9,6,7,8,4,5 –  Apr 20 '16 at 21:17
  • @MrPython Added all three.. Sentence, list of positions, positions as string. Delete what you don't need – jDo Apr 20 '16 at 21:17
  • Sorry I don't quite understand. Could you please write out exactly what I need to replace and what with. –  Apr 20 '16 at 21:19
  • @MrPython I changed it but I also wrote it in the asnwer: *"You could, of course, add 1 to all indices in the list comprehension if you wanted it to start at 1."*. Now the numbers start from 1 rather than 0 – jDo Apr 20 '16 at 21:20
  • @MrPython I meant that I added 3 different print statements and you can just delete the two you don't want; be it the recreated string, the list, the string of positions, etc. You have three different outputs to choose from. – jDo Apr 20 '16 at 21:21
  • @MrPython Do what? Add 1 to all numbers in the list? Check my answer if that's what you mean – jDo Apr 20 '16 at 21:23
  • Can you just write out the whole code please, i'm getting a bit confused :) –  Apr 20 '16 at 21:24
  • 1
    @MrPython I did!? That *is* the whole code – jDo Apr 20 '16 at 21:24
  • But with the other bits you added on please? –  Apr 20 '16 at 21:30
  • Don't worry I've got it. Thanks :) –  Apr 20 '16 at 21:31
  • @MrPython You're welcome – jDo Apr 20 '16 at 21:50
1
sentence = 'ASK NOT WHAT YOUR COUNTRY CAN DO FOR YOU ASK WHAT YOU CAN DO FOR YOUR COUNTRY'
words = sentence.split()

# Counting backwards through the words means the last seen one will have 
# the lowest index without needing 'if' tests or incrementing counters.
positions = {word:index for index, word in reversed(list(enumerate(words, 1)))}

print(' '.join(str(positions.get(word)) for word in words))

Try it on repl.it here: https://repl.it/CHvy/0

TessellatingHeckler
  • 27,511
  • 4
  • 48
  • 87
0

Not terribly efficient, but two lines.

words = sentence.split()
positions = [words.index(word) + 1 for word in words]

Note that list.index(entry) will return the index of the first occurrence of entry. If you're okay with 0-based indices, then the following is pretty concise:

positions = list(map(words.index, words))
Jared Goguen
  • 8,772
  • 2
  • 18
  • 36