I have the the following input string:
1 imported box of chocolates at 10.00 1 imported bottle of perfume at 47.50
I would like to use the Java Scanner class to parse this input to create a list of product objects for example.
Please note the input line consists of multiple products (two in this case) as follows:
Quantity: 1
Name: imported box of chocolates
Price: 10.00
Quantity: 1
Name: imported bottle of perfume
Price: 47.50
Ideally I would like to parse the first product portion of the line and then the next product portion.
I know how to do this using regex etc but the question is:
What is the best way to use the Java Scanner to parse the input line?
Thank you.
I would just use splitting on space which is what Scanner does by default, and do the parsing myself according to the following rule.
ORDER := QUANTITY DESCRIPTION at PRICE ORDER | ""
QUANTITY := Integer
DESCRIPTION := String
PRICE := Float
For simplicity you can do it like below, you will have to include some error handling of course. A better option would be to use a tool like antlr which will do all the heavy lifting for you.
Scanner sc = new Scanner(System.in);
ArrayList<Product> products = new ArrayList<>();
while (sc.hasNext()) {
int quantity = sc.nextInt();
StringBuilder description = new StringBuilder();
while (!(String token = sc.next()).equals("at")) {
description.append(token);
}
float price = sc.nextFloat();
Product p = new Product(quantity, description.toString(), price);
products.add(product);
}
Hope this helps.
Related
Basically, I have to go through all baselines of an object until I get the author who modified "_ReqStatus" attribute and copy that value in "_Ownr" attribute. Everything is working fine for the current baseline, but I cannot get through the older baselines of the module. I have to mention that I run the script for 2000 objects each one having at least 20 baselines.
My code looks like this:
//scriptul recunoaste obiectele cu "ReqStatus modifica"
pragma runLim, 0
Module m = current
History h
HistoryType ht
Object o
string attributName
string attributNameBaseline
string authorName
string newOwner
Baseline lBaseLine
noError()
for o in entire m do {
**for lBaseLine in module(o) do{ //These 2 code lines were my try to load all baselines
Module lBaseMod = load(module(o), false) //but with no results**
for h in o do
{
string owner = ""
attributName=""
attributName = h.attrName
authorName=""
owner = o."_Owner"
if isDeleted(o) then continue
if(attributName=="_ReqStatus")
{
authorName=h.author
//print authorName
//print "\n"
if(null owner)
{
print identifier(o)
print "\n"
newOwner = authorName
print newOwner"\n"
o."_Ownr" = newOwner
//print newOwner
break
}
}
}
}
}
ErrMess = lastError()
Thanks
Tony Goodman provides a script "Smart History Viewer" at http://www.smartdxl.com/content/?p=418, Michael Sutherland has one at https://www.ibm.com/mysupport/s/forumsquestion?id=0D50z00006HIGSUCA5, also, if you do a search on https://www.ibm.com/mysupport/s/forumshome for e.g. "dxl history" you might find some more code examples which should help you with this topic.
Your problem is the variable o. It is set only in the loop for o in entire m, it always refers to the o in the current version of m, never to the corresponding Object in a baseline. When you open the Module lBaseMod, o is not automatically reassigned.
So, use a new variable of type Object, set it to the Object in the baseline corresponding to o and browse through this new Object's history, see the linked scripts for reference.
Also, you should rework the flow of your script. With your approach, you open all the Baselines of m for each Object. In your case this means 2000 * 20 load and close. It will be much faster (though not necessarily less memory consuming) to open all the baselines of m in an outer loop, probably using a Skip list to collect the necessary information.
Also note that when you test your script, "print" becomes very slow after some time. It will be faster if you remember all the values that you want to print e.g. in a Buffer and print it at the end of your script, or write the output to a file.
I want to find specified text within a string in a given column, and count how many times that string is repeated throughout the entire column.
For example, Find "XX" within a string in a column and print to dialogue box the number of times that text was found.
Module m = current
Object o
string s
string x
int offset = null
int len = null
int c
for o in m do
{
string s = probeAttr_(o, "AttributeA")
x = o."Object Text" ""
if(findPlainText(s, "XX", offset, len, false)){
print "Success "
} else {
print "Failed to match"
}
}
I have tried to use command findPlainText but I am inadvertently passing every object as true.
As well I placed the output to print 'success' or 'Failed to match' so I can at least get a number count of what is being passed. Unfortunately it seems like everything is being passed!
My understanding is that 'probeAttr_(o, "AttributeA")' allows me to specify and enter what column to search. As well o."Object Text" "" now allows me to look within any object and search for any text contained. I also realize that variable x is not being used but assume it has some way of being used to solve this issue.
I only use DOORS at a surface level but having this ability will save other staff tons of time. I realize this may be accomplished using the DOORS advanced filtering capability but I'd be able to compound this code with other simple commands to save time.
Thank you in advance for your help!!
If you want to count every occurence of a specified string in a text in an attribute for all objects, I think Mike's proposal is the correct answer. If you are only interested, if the specified string occurs once in that object's attribute, I suggest using Regexp, as I find it very fast, quite powerful and nevertheless easy to use, e.g.:
Regexp reSearch = regexp2 "XX"
int iCounter = 0
string strOT = ""
for o in m do {
strOT = o."Object Text" ""
if (reSearch strOT) {
iCounter++
}
}
print "Counted: '" iCounter "'\n"
Most of this has been answered in (DXL/Doors) How to find and count a text in a string?
You can easily exchange the "print" with a counter.
I am Currently working on Receipt.
in receipt I have three labels. Product quantity,product name and product price.
when I product name is big than it should go to next line
I am using EPSON Printer to Print data.
I am able to do Print.but when product name is big than I am getting receipt alignment issue like this image
but I want to receipt like this
aligmnet issues I get when product name is big.to overcome this issue I think I should use range according to length of string
I am using this code
pName = "Chicken"
if pName.characters.count > 13 {
var x = (pName as NSString).substringWithRange(NSMakeRange(0, 13))
x = x.stringByAppendingFormat("%# ", (pName as NSString).substringWithRange(NSMakeRange(13, pName.characters.count - 13)))
x = x.stringByAppendingFormat("%# ", (pName as NSString).substringWithRange(NSMakeRange(13,26)))
textData.appendString(x)
}
but I am not getting proper alignment.
can you help me to help how to make aligmemnt proper.
I am very familiar with using java.util.Scanner with next(), hasNext(), nextInt(), nextLine(), and the like to parse input.
Is there something else I should use in Scala?
This data isn't structured according to a grammar; it's more ad-hoc than that.
For example, lets say I had a inventory. Each line of input starts with the name, then has the quantity of those items, then has the ids for those items
Firetruck 2 A450M A451M
Machine 1 QZLT
Keyboard 0
I see that Console has methods such as readInt(), but that reads an entire line of input; the equivalent of nextInt() doesn't seem to exist.
java.util.Scanner obviously does the trick. But is there something else I should use (for example, something that returns Scala rather than Java types)?
No there is no equivalent Scala implementation. But I don't see a reason for one as java.util.Scanner would work perfectly fine and all java primitives types would be converted to Scala types implicitly.
So as for "for example, something that returns Scala rather than Java types", Scanner will return scala types when used in scala.
better-files is a Scala library that provides faster, safer and more idiomatic replacement for java.util.Scanner and provides more operations like peeking and scanning.
Link: https://github.com/pathikrit/better-files#scanner
Code sample:
val data = (home / "Desktop" / "stocks.tsv") << s"""
| id Stock Price Buy
| ---------------------
| 1 AAPL 109.16 false
| 2 GOOGL 566.78 false
| 3 MSFT 39.10 true
""".stripMargin
val scanner: Scanner = data.newScanner.skip(lines = 2)
assert(scanner.peekLine == Some(" 1 AAPL 109.16 false"))
assert(scanner.peek == Some("1"))
assert(scanner.nextInt == Some(1))
assert(scanner.peek == Some("AAPL"))
assert(scanner.nextString() == Some("AAPL"))
assert(scanner.nextInt() == None)
assert(scanner.nextDouble() == Some(109.16))
assert(scanner.nextBoolean() == Some(false))
while(scanner.hasNext) {
println(scanner.nextInt(), scanner.next(), scanner.nextDouble(), scanner.nextBoolean())
}
With the input data denoted by spaces and newlines this can be nicely done with map and split on each line from input.
def input =
"""Firetruck 2 A450M A451M
Machine 1 QZLT
Keyboard 0"""
case class Item(name: String, quantity: Int, ids: Array[String])
scala> input.lines.map(_.split(" ")).map(split => Item(split(0), split(1).toInt, split.takeRight(2))).toList
res0: List[Item] = List(Item(Firetruck,2,[Ljava.lang.String;#6608842e), Item(Machine,1,[Ljava.lang.String;#391e1c57), Item(Keyboard,0,[Ljava.lang.String;#67d6b10c))
scala>res0.foreach(println(_))
Item(Firetruck,2,[Ljava.lang.String;#6608842e)
Item(Machine,1 [Ljava.lang.String;#391e1c57)
Item(Keyboard,0,[Ljava.lang.String;#67d6b10c)
I am generating a unique and random alphanumeric string segment to represent certain links that will be generated by the users. For doing that I was approaching with "uuid" number to ensure it's uniqueness and randomness, but, as per my requirements the string shouldn't be more than 5 characters long. So I dropped that idea.
Then I decided to generate such a string using random function of ruby and current time stamp.
The code for my random string goes like this:-
temp=DateTime.now
temp=temp + rand(DateTime.now.to_i)
temp= hash.abs.to_s(36)
What I did is that I stored the current DateTime in a temp variable and then I generated a random number passing the current datetime as parameter. Then in the second line actually added current datetime and random number together to make a unique and random string.
Soon I found,while I was testing my application in two different machines and send the request at the same time, it generated the same string(Though it's rare) once after more than 100 trials.
Now I'm thinking that I should add one more parameter like mac address or client ip address before passing to_s(36) on temp variable. But can't figure out how to do it and even then whether it will be unique or nor...
Thanks....
SecureRandom in ruby uses process id (if available) and current time. You can use the urlsafe_base64(n= 16) class method to generate the sequence you need. According to your requirements I think this is your best bet.
Edit: After a bit of testing, I still think that this approach will generate non-unique keys. The way I solved this problem for barcode generation was:
barcode= barcode_sql_id_hash("#{sql_id}#{keyword}")
Here, your keyword can be time + pid.
If you are certain that you will never need more than a given M amount of unique values, and you don't need more than rudimentary protection against guessing the next generated id, you can use a Linear Congruentual Generator to generate your identificators. All you have to do is remember the last id generated, and use that to generate a new one using the following formula:
newid = (A * oldid + B) mod M
If 2³² distinct id values are enough to suit your needs, try:
def generate_id
if #lcg
#lcg = (1664525 * #lcg + 1013904223) % (2**32)
else
#lcg = rand(2**32) # Random seed
end
end
Now just pick a suitable set of characters to represent the id in as little as 6 character. Uppercase and lowercase letters should do the trick, since (26+26)^6 > 2^32:
ENCODE_CHARS = [*?a..?z, *?A..?Z]
def encode(n)
6.times.map { |i|
n, mod = n.divmod(ENCODE_CHARS.size)
ENCODE_CHARS[mod]
}.join
end
Example:
> 10.times { n = generate_id ; puts "%10d = %s" % [n, encode(n)] }
2574974483 = dyhjOg
3636751446 = QxyuDj
368621501 = bBGvYa
1689949688 = yuTgxe
1457610999 = NqzsRd
3936504298 = MPpusk
133820481 = PQLpsa
2956135596 = yvXpOh
3269402651 = VFUhFi
724653758 = knLfVb
Due to the nature of the LCG, the generated id will not repeat until all 2³² values have been used exactly once each.
There is no way you can generate a unique UUID with only five chars, with chars and numbers you have a basic space of around 56 chars, so there is a max of 56^5 combinations , aprox 551 million (Around 2^29).
If with this scheme you were about to generate 10.000 UUIDs (A very low number of UUIDs) you would have a probability of 1/5.000 of generating a collision.
When using crypto, the standard definition of a big enough space to avert collisions is around 2^80.
To put this into perspective, your algorithm would be better off if it generated just a random integer (a 32 bit uint is 2^32, 8 times the size you are proposing) which is clearly a bad idea.