-1
import random
com=input("")
if com.startswith("/tip"):
    numlines=sum(1 for line in open("C:\\Users\\Jace\\Desktop\\Python Programs\\Quote\\tip.txt"))-1
    randomint=random.randint(0, numlines)
    with open("C:\\Users\\Jace\\Desktop\\Python Programs\\Quote\\tip.txt", "r") as f:
        i=1
        for line in f:
            if i==randomint:
                break
            i+=1
    print(line.strip("\n"))

This is the part of the code for my random tips from a file so far. I wish to add another part of code where it adds all strings with any occurrence of the input placed after "/tip ", for example, if I were to type "/tip Hello", it would compile all lines in the text file with "Hello" in the string and do a random.choice() from the list, printing the one chosen. I don't really know where to start with this, any help would be appreciated. Thanks in advance!

  • 1
    Can you show tip.txt – Keatinge May 11 '16 at 18:56
  • In your example, ```line``` is a string - you could use [```in```](https://docs.python.org/3/reference/expressions.html#membership-test-operations) to see if the tip is in the string. – wwii May 11 '16 at 18:59

2 Answers2

1

You don't have to store all of the lines in a list. You can read the lines, selecting one at random and discarding the rest. This is called "resevoir sampling".

Your code might look like this:

import random

def random_line(iterator):
    result = None
    for n, item in enumerate(iterator):
        if random.randint(0,n) == 0:
            result = item
    return result

# A random line
with open('tip.txt') as f:
    print random_line(f) or "No tip for you!"

# A random line that has 'Hello'
with open('tip.txt') as f:
    print random_line(line for line in f if 'Hello' in line) or "nothin!"

As a more special case, this code randomly chooses a matching line from the tips file, but falls back to a random non-matching line if no match exists. It has the advantages of reading the input file exactly once, and not having to store the entire tips file in memory.

import random

def random_line_with_fallback(iterator, match = lambda x: True):
    result_match = None
    result_all = None
    n_match = n_all = 0
    for item in iterator:
        if match(item):
            if random.randint(0, n_match) == 0:
                result_match = item
            n_match += 1
        if random.randint(0, n_all) == 0:
            result_all = item
        n_all += 1
    return (result_match or result_all).strip()

# A random line
with open('tip.txt') as f:
    print random_line_with_fallback(f)

# Another way to do a random line. This depends upon
# the Python feature that  "'' in line" will always be True. 
com = ''
with open('tip.txt') as f:
    print random_line_with_fallback(f, lambda line: com in line)

# A random line that has 'Hello', if possible
com = 'Hello'
with open('tip.txt') as f:
    print random_line_with_fallback(f, lambda line: com in line)

References:

Community
  • 1
  • 1
Robᵩ
  • 163,533
  • 20
  • 239
  • 308
  • How would I make it so that it would default to the 'random line' if the 'random line with hello' doesn't exist? I've been trying `if com in line:` etc, and trying to adapt your code, but it doesn't seem to want to work when I make additions, saying that **line** doesn't exist at that point – Synthestra May 11 '16 at 20:14
  • I would want to preserve the single-pass non-accumulating nature of the reservoir algorithm. I have included an example in my recent edit. – Robᵩ May 11 '16 at 21:14
0

I think this is what you want, process each line of a text file, checking if the line has the word you're looking for. If so, add it to a list, and the randomly select one "line" for all possible "lines".

lines = []
with open("tip.txt", "r") as f:
    for line in f:
        if com in line:
            lines.append(line)
print(random.choice(lines))
L3viathan
  • 26,748
  • 2
  • 58
  • 81
Tony
  • 1,318
  • 1
  • 14
  • 36
  • 1
    `print(random.choice(lines))` is much cleaner than `print( lines[ random.randint(0, len(lines)-1) ] )` – Keatinge May 11 '16 at 19:02