I'm really fresh to Python and need help reading information from txt file. I have a large C++ app need to duplicate it in Python. Sadly I have no idea where to start. I've been reading and watching some tutorials, but little help from them and I'm running out of time.
So my task is:
I have a shopping list with:
-Name of the item, price and age.
I also need to create two searches.
Search whether the item is in the shop (comparing strings).
if name of the item is == to the input name.
Search by age. Once the program finds the items, then it needs to print the list according to the price - from the lowest price to the highest.
For example you input age 15 - 30, the program prints out appropriate
items and sorts them by the price.
Any help would be nice. At least from where I could start.
Thank you.
EDITED
So far, I have this code:
class data:
price = 0
agefrom = 0
ageto = 0
name = ''
# File reading
def reading():
with open('toys.txt') as fd:
toyslist = []
lines = fd.readlines()
for line in lines:
information = line.split()
print(information)
"""information2 = {
'price': int(information[1])
'ageftom': int(information[2])
'ageto': int(information[3])
#'name': information[4]
}"""
information2 = data()
information2.price = int(information[0])
information2.agefrom = int(information[1])
information2.ageto = int(information[2])
information2.name = information[3]
toyslist.append(information2)
return toyslist
information = reading()
I HAVE A PROBLEM WITH THIS PART. I want to compare the user's input with the item information in the txt file.
n_search = raw_input(" Please enter the toy you're looking for: ")
def name_search(information):
for data in information:
if data.name == n_search:
print ("We have this toy.")
else:
print ("Sorry, but we don't have this toy.")
If you want to fins something in a list it's generally as straightforward as:
if "apple" in ["tuna", "pencil", "apple"]
However, in your case, the list to search is a list of lists so you need to "project" it somehow. List comprehension is often the easiest to reason about, a sort of for loop in a for loop.
if "apple" in [name for name,price,age in [["tuna",230.0,3],["apple",0.50,1],["pencil",1.50,2]]]
From here you want to start looking at filters whereby you provide a function that determines whether an entry is matched or not. you can roll your own in a for loop or use something more functional like 'itertools'.
Sorting on a list is also easy, just use 'sorted(my_list)' supplying a comparator function if you need it.
Examples as per your comment...
class ShoppingListItem:
def __init__(self,name,price,age):
self.name=name
self.price=price
self.age=age
or
from collections import namedtuple
sli = namedtuple("ShoppingListItem",['name','age','price'])
Related
I want to make a multi choice question program in SML.
I have a text file whose content is structured as follows:
category1:Basic sml/sql
1-How many subsets does the power set of an empty set have?
A) One
B) Two
C) Three
D) Zero
Ans:A
2-What is the cardinality of the set of odd positive integers less than 10?
A) 20
B) 3
C) 5
D) 10
Ans:C
Each category has more than 5 questions
Each question belongs to a category
For each question there are 4 proposed answers followed by the answer on another line
I would like, to be able to retrieve and display to the user just the question (a random question) and the corresponding proposed answers. I have written this function that allows me to retrieve line by line all the content of my file. But I'm still stuck on how to unload a question-answer block.
fun getFromFile(file_name) =
let
val file = TextIO.openIn file_name
val text = TextIO.inputAll file
val _ = TextIO.closeIn file
in
String.tokens (fn c => c = #"\n") text
end
val table = getFromFile("question_file.txt");
How could I proceed? Is it possible to retrieve the lines of the file without passing them through a table first (retrieve the text directly)?
I'm still stuck on how to unload a question-answer block.
How could I proceed?
Find a way to encode multiple categories that contain multiple questions that contain multiple answers each. And once you have found a way to store that to a file (a file format), write a decoder. Your current decoder is a line decoder. You can encode things within things within things using lines, but you can also do it other ways.
For example, using JSON:
[
{
"category": "Basic sml/sql",
"questions": [
{
"question": "How many subsets does the power set of an empty set have?",
"answers": [
{ "answer": "Zero", "correct": false },
{ "answer": "One", "correct": true },
{ "answer": "Two", "correct": false },
{ "answer": "Three", "correct": false }
]
},
...
]
},
...
]
If relying on third-party libraries seems too difficult, you could come up with a file format yourself, e.g. a line-based one:
CATEGORY Basic sml/sql
QUESTION How many subsets does the power set of an empty set have?
ANSWER Zero
ANSWER_CORRECT One
ANSWER Two
ANSWER Three
QUESTION ...
So given your line-based reader, loop over each line and look at the first word:
If it's CATEGORY, start a new category.
If it's QUESTION, start a new question within the current category.
If it's ANSWER or ANSWER_CORRECT, provide an option in the current question within the current category.
This suggests a recursive function (since it needs to go over each line) that takes a number of parameters: The current category, the current question, and the total set of categories, questions and answers so far.
At this point you probably have to think: How do I store categories of questions with multiple answers in memory? What data type should I be using? E.g. using type aliases, you could express your data model like this:
type answer_option = string * bool
val example_answer_option = ("Zero", false) : answer_option
type question_answers = string * answer_option list
val example_question_answers =
("How many subsets does the power set of an empty set have?",
[
("Zero", false),
("One", true),
("Two", false),
("Three", false)
]
) : question_answers
type category = string * question_answers list
val example_category =
("Basic sml/sql",
[ example_question_answers ]
) : category
val example_categories = [ example_category ] : category list
The way SML type aliases work is that you get all of those expanded into the primitive types they consist of, so they may show up in your REPL as such:
> type answer_option = string * bool
type question_answers = string * (string * bool) list
type category = string * (string * (string * bool) list) list
which is considerably less readable and is one reason to use alternatives like datatype, abstype or opaque modules.
Going with this, however, you may define a stub like:
fun parse (line::lines, currentQuestion, currentAnswers, currentCategory, acc) =
case splitFirstWord line of
("CATEGORY", cat) => ...
| ("QUESTION", q) => ...
| ("ANSWER", aWrong) => ...
| ("ANSWER_CORRECT", aRight) => ...
| _ => raise Fail ("Unknown: " ^ line)
Now there are two sub-problems:
splitFirstWord doesn't actually exist (yet).
There is a whole lot of book-keeping of current state.
Good luck!
Is it possible to retrieve the lines of the file without passing them through a table first (retrieve the text directly)?
I don't really understand this question. Unarguably, yes?
If by "table" you mean some kind of indexable data structure like a list:
Just don't call String.tokens (fn c => ...) on the input.
This gives you a basic string.
Note that table is just the name of a value binding.
If you like, you can pass it through a chair instead:
fun getFromFile(file_name) =
let
val file = TextIO.openIn file_name
val text = TextIO.inputAll file
val _ = TextIO.closeIn file
in
text
end
val chair = getFromFile "question_file.txt"
Note also that the parenthesis around function arguments is not necessary in SML. In fact, if you think they are, you'll probably make a syntax mistake soon enough. Try to avoid redundant syntax for greater clarity.
The setup: A UITextField and a Tableview with suggested users
I try to have the following result:
I want users to be able to link other users.
Its working fine as long as I search with my last word in the array
let caption = captionTextView.text
let words = caption?.components(separatedBy: .whitespacesAndNewlines)
guard let searchingWord = words?.last else {return}
if searchingWord.hasPrefix("#") {
self.indicator.startAnimating()
let search = searchingWord.trimmingCharacters(in: CharacterSet.punctuationCharacters).lowercased()
}
But in case a user wants to adjust a username in the middle or at least not at the end of the array, the searching functions doesn't work properly as it still searches with the last word in the array
Example:
"Hey how are you #Lisa #Marcel #Thomas"
In case a user wants to change "#Lisa" to "#Lisbeth" the search function will search with Thomas as its the last word in the array
I wasn't able to get the word I am working at, only last and first words in the array, however I am able to get the current cursor location with
let cursor = captionTextView.cursorOffset!
which is an extension.
So how do I get the word I am working at up until the next "#" to the left und the next blank space to the right? Thanks in advance!
Maybe try something like this:
if let selectedRange = textview.selectedTextRange {
let cursorOffset = textview.offset(from: textview.beginningOfDocument, to: selectedRange.start)
let text = textview.text
let substring = text?.prefix(cursorOffset)
let editedWord = substring?.split(separator: "#")
}
(written on a phone, and untested)
One solution is Regular Expression
let string = "Hey how are you #Lisa #Marcel #Thomas"
let searchingWord = "Lisa"
let replacingWord = "Lisbeth"
let pattern = "#\(searchingWord)\\s"
string.replacingOccurrences(of: pattern, with: "#\(replacingWord) ", options: .regularExpression)
The pattern searches for # followed by the searching word followed by a whitespace character.
Since you say things are working the way you want if the last word is the one that has a username in it you just need to loop over all the words. Depending on your needs you may need to keep track of the usernames that were in the text before to save you from searching for the same user multiple times, but an array of used usernames should sort that for you.
Also, unless you want to prevent users from having underscores and the such in their names you should tweak the way in which you remove the # symbol as well.
guard let words = captionTextView.text?.components(separatedBy: .whitespacesAndNewlines) else { return }
for word in words where word.hasPrefix("#") {
self.indicator.startAnimating()
let search = word.replacingOccurrences(of: "#", with: "").lowercased()
}
Sticking the above code into a playground that uses the sample string you supplied in place of captionTextView.text? and printing search each time yielded…
lisa
marcel
thomas
I need some help with my lua script for a game. I need to check if my inventory in the game contains any id from a list.
Here's a piece of my list:
local Game_Items = {
{id = 7436, name = "angelic axe", value = 5000},
{id = 3567, name = "blue robe", value = 10000},
{id = 3418, name = "bonelord shield", value = 1200},
{id = 3079, name = "boots of haste", value = 30000},
{id = 7412, name = "butcher's axe", value = 18000},
{id = 3381, name = "crown armor", value = 12000}
}
The following code might look a bit weird since you don't know what it's for, but it's basically this: the list above is a list of items in my game, and inside the game theres an inventory where you can keep items and stuff. Now I want to check if my inventory contains any of those IDs.
I tried adding 2 of the id's manually and it worked, but my list of items contains over 500 items in total and I don't want to write them all out. Is there a way to put the whole list and check if it's in there somehow?
if not table.contains({ 3035, 3043, Game_Items[id] }, tempItemCounter.id) then
This is what I tried so far. Those two first id's work 3035 and 3043, then I tried all my whole list and only check the Ids. but I dont know how to do that. That code does not work. Could anyone just help me include the whole list of id's in the table.contains ?
Basically wanna include my whole list in that line, without typing out all IDs manually.
Shouldn't Game_Items[id] work? Doesn't that mean all the "id" inside "Game_Items"?
Thanks!
No it doesn't mean that. If foo is a table, then foo[id] looks for a field in foo that is called whatever id refers to, such as a string (so if id is 1 you will get foo[1], if id is "bar" you will get foo.bar, etc).
You can't do it in one line, but you can create a function that will allow you to write your if condition. I'm not sure what tempItemCounter is but assuming that your inventory is a map of keys to entries of the form
inventory = {
[1234] = {....},
[1235] = {....},
...
}
where each integer key is unique, and assuming you want true only if all items are in inventory, then you could do this:
function isAllInInventory(items, inventory)
for i,item in ipairs(items) do
if inventory[item.id] == nil
return false
end
end
return true
end
if isAllInInventory(Game_Items, inventory) then
...
end
While trying to make a simple register/signup client only application for a personal project. I'm trying to load a list of users from a file, and compare them to a possible username. If the username already exists, the program will give them an error.
Here is a condensed clone of the code:
u1 = str(input("Input username: "))
t = open("userlistfile","r")
userlist = t.readline()
y = 0
for x in range(0, len(userlist)-1):
if userlist[y] == u1:
print("\n !Error: That username (",u1,") is already taken!")
y += 1
The user list is stored in a file so that it can opened, appended, and saved again, without being stored in the program. My current issue is that the userlist is saved as a string rather than an array. Is there a better way to do this? Thank you.
EDIT: Thanks to user lorenzo for a solution. My Friends are telling me to post a quick (really simple) copy of a for you guys who can't figure it out.
New code:
u1 = str(input("Input username: "))
t = open("userlistfile","r")
userlist = t.read() #Readline() changed to Read()
userlist = userlist.split('--') #This line is added
y = 0
for x in range(0, len(userlist)-1):
if userlist[y] == u1:
print("\n !Error: That username (",u1,") is already taken!")
y += 1
Example text file contents:
smith123--user1234--stacky
This line will seperate the string at the ('--') seperators and append each split part into an array:
userlist = userlist.split('--')
#Is used so that this (in the text file)
Smith123--user1234--stacky
#Becomes (in the program)
userlist = ['Smith123','user1234','stacky']
Sorry for the long post... Found it very interesting. Thanks again to Lorenzo :D.
userlist = t.readline()
reads one line from the file as a string. Iterating, then, gets characters in the string rather than words.
You should be able to get a list of strings (words) from a string with the split() method of strings or the more general re.split() function.
I just have a question about writing a function that will search a directory for the most recent log in a directory. I currently came up with one, but I'm wondering if there is a better (perhaps more proper) way of doing this.
I'm currently using hdsentinel to create logs on computer and placing the log in a directory. The logs are saved like so:
/directory/hdsentinel-computername-date
ie. C:/hdsentinel-owner-2010-11-11.txt
So I wrote a quick script that loops through certain variables to check for the most recent (within the past week) but after looking at it, I'm question how efficient and proper it is to do things this way.
Here is the script:
String directoryPath = "D:"
def computerName = InetAddress.getLocalHost().hostName
def dateToday = new Date()
def dateToString = String.format('%tm-%<td-%<tY', dateToday)
def fileExtension = ".txt"
def theFile
for(int i = 0; i < 7; i++) {
dateToString = String.format('%tY-%<tm-%<td', dateToday.minus(i))
fileName = "$directoryPath\\hdsentinel-$computerName-$dateToString$fileExtension"
theFile = new File(fileName)
if(theFile.exists()) {
println fileName
break;
} else {
println "Couldn't find the file: " + fileName
}
}
theFile.eachLine { print it }
The script works fine, perhaps it has some flaws. I felt I should go ahead and ask what the typical route is for this type of thing before I continue with it.
All input is appreciated.
Though a bit messy, you could implement a multi-column sort via the 'groupBy' method (Expounding on Aaron's code)..
def today = new Date()
def recent = {file -> today - new Date(file.lastModified()) < 7}
new File('/yourDirectory/').listFiles().toList()
.findAll(recent)
.groupBy{it.name.split('-')[1]}
.collect{owner, logs -> logs.sort{a,b -> a.lastModified() <=> b.lastModified()} }
.flatten()
.each{ println "${new Date(it.lastModified())} ${it.name}" }
This finds all logs created within the last week, groups them by owner name, and then sorts according to date modified.
If you have files other than logs in the directory, you may first need to grep for files containing 'hdsentinel.'
I hope this helps.
EDIT:
From the example you provided, I cannot determine if the least significant digit in the format:
C:/hdsentinel-owner-2010-11-11.txt
represents the month or the day. If the latter, sorting by file name would automatically prioritize by owner, and then by date created (without all of the chicanery of the above code).
For Instance:
new File('/directory').listFiles().toList().findAll(recent).sort{it.name}
Hopefully this helps some..This sorts a given path by date modified in a groovier way. The lists them out.
you can limit the list, and add other conditions in the closure to get the desired results
new File('/').listFiles().sort() {
a,b -> a.lastModified().compareTo b.lastModified()
}.each {
println it.lastModified() + " " + it.name
}
As I was trying to solve a similar problem, learnt a much cleaner approach.
Define a closure for sorting
def fileSortCondition = { it.lastModified() }
And File.listFiles() has other variation which accepts FileFilter and FilenameFilter in Java, and these interfaces has a single method called accept, Implement the interface as a closure.
def fileNameFilter = { dir, filename ->
if(filename.matches(regrx))
return true
else
return false
} as FilenameFilter
And lastly
new File("C:\\Log_Dir").listFiles(fileNameFilter).sort(fileSortCondition).reverse()
Implement FileFilter interface if filtering is to be done by File attributes.
def fileFilter = { file ->
if(file.isDirectory())
return false
else
return true } as FileFilter