Read first element and next element from a file SCALA - scala

I am reading a file that contain 277272 lines with Int triples (s,p,o) like:
10,44,22
10,47,12
15,38,3
15,41,30
16,38,5
16,44,15
16,47,18
22,38,21
22,41,42
34,44,40
34,47,36
40,38,39
40,41,42
45,38,27
45,41,30
46,44,45
46,47,48
From this file I create a Random access file object in order to navigate trough this file. However I want to extract some specific values that are in the first column, an example can be that I want to extract the values of the row that contains 16 in the first column, then I choose a pointer that is in the half, something like:
var lengthfile = (file.length().asInstanceOf[Int])
var initpointer = lengthfile/2
Then I analize if the first value is 16, if not I did a procedure to move the pointer to the nextlines, or as in this case in the back lines. Once I detect that the first value is 16, I need to know if it was in the first row, the sceond or the last one. The functions that I present here are to get the first value of the line where I have the pointer, and to know the first value from the next line.
def firstvalue(pf: Int, file:RandomAccessFile): List[Int] ={
//val file = new RandomAccessFile(filename, "r")
var pointer = pf
var flag = true
var fline = Option("a")
if (pointer <= file.length()-1){
file.seek(pointer)
fline = Option(file.readLine)
}
else {
pointer = file.length().toInt-12
file.seek(pointer)
fline = Option(file.readLine)
}
while (flag)
{
if (fline.get != "")
{
if (pointer == 0)
{
file.seek(pointer)
fline = Option(file.readLine)
pointer -= 1
flag = false
}
else{
pointer -= 1
file.seek(pointer)
fline = Option(file.readLine)
}
}
else if (fline.get == ""){
flag = false
}
}
pointer += 1
file.seek(pointer)
val line = Option(file.readLine)
val spl = line.get.split(',')
val p = spl.apply(0).toInt
//file.close()
val l = pointer :: p :: Nil
l
}
//def nextvalue(pf: Int, filename:String): List[Int] = {
//val file = new RandomAccessFile(filename, "r")
def nextvalue(pf: Int, file:RandomAccessFile): List[Int] = {
//val file = new RandomAccessFile(filename, "r")
var pointer = pf
var p = 0
var flag = true
var lastline = false
var fline = Option ("a")
if (pointer <= file.length()-1){
file.seek(pointer)
fline = Option(file.readLine)
}
//fline = Option(file.readLine)
while (flag){
if (fline.get != "")
{
if (fline == None)
{
flag = false
lastline = true
}
else{
pointer = file.getFilePointer.toInt
fline = Option(file.readLine)
flag = false
}
}
else if (fline.get == ""){
fline = Option(file.readLine)
flag = false
}
}
if (lastline == false)
{
//file.close()
if (fline != None){
val spl = fline.get.split(',')
p = spl.apply(0).toInt
}
}
val l = pointer :: p :: Nil
l
}
However I have a prformance problem, because I am reading character by character, I am trying to fix that during a lot of days, and I don't have a solution. I don't know If perhaps the file object have a function to read back lines, or something that allows to me improve this code? How can I improve this code?

Source
.fromFile(file)
.getLines
.zipWithIndex
.filter(_._1.startsWith("16,"))
Will give you all lines, that start with "16", along with their indices in the file. That should be faster then seeking back and forth ...

Related

Lexical Analyzer not getting the next character

So I am working on a project where we are making a small compiler program but before I can move on to the other parts I am having troubles with getting the lexical analyzer to output anything after '\BEGIN' afterwards I debugged it and it seems the value is stuck in a loop where the condition is saying the next character is always a newline. Is it because I haven't added the pattern matching yet to the defined tokens?
Here is the code
import java.util
//import com.sun.javafx.fxml.expression.Expression.Parser.Token
/*Lexical analyzer will be responsible for the following:
- finds the lexemes
- Checks each given character determining the tokens
* */
class MyLexicalAnalyzer extends LexicalAnalyzer {
//Array full of the keywords
//val SpecialCharacters = List(']', '#', '*', '+', '\\', '[', '(',')', "![", '=')
val TEXT = "[a-z] | _ | 0-9 | [A-Z]:"
private var sourceLine: String = null
private val lexeme: Array[Char] = new Array[Char](999)
private var nextChar: Char = 0
private var lexLength: Int = 0
private var position: Int = 0
private val lexems: util.List[String] = new util.ArrayList[String]
def start(line: String): Unit = {
initializeLexems()
sourceLine = line
position = 0
getChar()
getNextToken()
}
// A helper method to determine if the current character is a space.
private def isSpace(c: Char) = c == ' '
//Defined and intialized tokens
def initializeLexems(): Any = {
lexems.add("\\BEGIN")
lexems.add("\\END")
lexems.add("\\PARAB")
lexems.add("\\DEF[")
lexems.add("\\USE[")
lexems.add("\\PARAE")
lexems.add("\\TITLE[")
lexems.add("]")
lexems.add("[")
lexems.add("\\")
lexems.add("(")
lexems.add(")")
lexems.add("![")
lexems.add("=")
lexems.add("+")
lexems.add("#")
}
//val pattern = new regex("''").r
def getNextToken() ={
lexLength = 0
// Ignore spaces and add the first character to the token
getNonBlank()
addChar()
getChar()
// Continue gathering characters for the token
while ( {
(nextChar != '\n') && (nextChar != ' ')
}) {
addChar()
getChar()
}
// Convert the gathered character array token into a String
val newToken: String = new String(lexeme)
if (lookup(newToken.substring(0, lexLength)))
MyCompiler.setCurrentToken(newToken.substring(0,lexLength))
}
// A helper method to get the next non-blank character.
private def getNonBlank(): Unit = {
while ( {
isSpace(nextChar)
}) getChar()
}
/*
Method of function that adds the current character to the token
after checking to make sure that length of the token isn't too
long, a lexical error in this case.
*/
def addChar(){
if (lexLength <= 998) {
lexeme({
lexLength += 1; lexLength - 1
}) = nextChar
lexeme(lexLength) = 0
}
else
System.out.println("LEXICAL ERROR - The found lexeme is too long!")
if (!isSpace(nextChar))
while ( {
!isSpace(nextChar)
})
getChar()
lexLength = 0
getNonBlank()
addChar()
}
//Reading from the file its obtaining the tokens
def getChar() {
if (position < sourceLine.length)
nextChar = sourceLine.charAt ( {
position += 1;
position - 1
})
else nextChar = '\n'
def lookup(candidateToken: String): Boolean ={
if (!(lexems.contains(candidateToken))) {
System.out.println("LEXICAL ERROR - '" + candidateToken + "' is not recognized.")
return false
}
return true
}
}
else nextChar = '\n'<- this is where the condition goes after rendering the first character '\BEGIN' then just keeps outputting in the debug console as listed below.
This is what the debug console it outputting after '\BEGIN' is read through
Can anyone please let me know why that is? This happens after I keep stepping into it many times as well.
Here is the driver class that uses the lexical analyzer
import scala.io.Source
object MyCompiler {
//check the arguments
//check file extensions
//initialization
//get first token
//call start state
var currentToken : String = ""
def main(args: Array[String]): Unit = {
val filename = args(0)
//check if an input file provided
if(args.length == 0) {
//usage error
println("USAGE ERROR: Must provide an input file. ")
System.exit(0)
}
if(!checkFileExtension(args(0))) {
println("USAGE ERROR: Extension name is invalid make sure its .gtx ")
System.exit(0)
}
val Scanner = new MyLexicalAnalyzer
val Parser = new MySyntaxAnalyzer
//getCurrentToken(Scanner.getNextToken())
//Parser.gittex()
for (line <- Source.fromFile(filename).getLines()){
Scanner.start(line)
println()
}
//.......
//If it gets here, it is compiled
//post processing
}
//checks the file extension if valid and ends with .gtx
def checkFileExtension(filename : String) : Boolean = filename.endsWith(".gtx")
def getCurrentToken() : String = this.currentToken
def setCurrentToken(t : String ) : Unit = this.currentToken = t
}
The code is operating as it is supposed to. The first line contains only the string \BEGIN so the lexical analyser is treating the end of the first line as an '\n' as shown in this method:
def getChar() {
if (position < sourceLine.length)
nextChar = sourceLine.charAt ( {
position += 1;
position - 1
})
else nextChar = '\n'
However, the comment directly above that method does not describe what the method actually does. This could be a hint as to where your confusion lies. If the comment says it should read from the file, but it is not reading from the file, maybe that's what you've forgotten to implement.

swift 3 variable used before begin initialized

I have an issue with my n variable. I cannot use n in for loop. Why? n was initialized before for loop. Please, help.
import Foundation
var n: Int
var t: Int
while(true){
var tt = readLine()
t = Int(tt!)!
if (t==0){
break
}
else if ( t < 0){
n = t*(-1)
}
else if(t > 0){
n = t
}
var arr : [[String]] = []
for i in 0..<n*2{
for y in 0..<n*2{
arr[i][y] = "."
}
}
}
A variable may be declared and not immediately initialized, as long as initialization is guaranteed before first use
The error is more subtle than at first glance. You may actually declare a property without initializing it, as long as all program flows leading to its first use ascertain initialization of it.
The issue is with the if, else if and else if block:
var n: Int // declaration
// ...
if (t == 0) {
break
}
else if (t < 0) {
n = t*(-1)
}
else if (t > 0){
n = t
}
// first use
for i in 0..<n*2 { /* ... */ }
Swift cannot not infer that this block is in fact exhaustive, and believes that there is a possibility that none of the above if statements holds, which, in the eyes of the compiler, would lead to the following program state:
program flow has not been broken (break)
and n has not been instantiated
As humans, however, we know that the if - else if - else if block above is indeed exhaustive, and can help the compiler out by simply changing the last if else statement to a simple else statement.
if (t == 0) {
break
}
else if (t < 0) {
n = t*(-1)
}
// if none of the above, t > 0
else {
n = t
}
On another note, the nested array access of non-existing array elements, arr[i][y] = "." will lead to a runtime exception, but this is another issue. In its current form, it looks as if the intent with the nested loops could be replaced with a nested array instantiation:
var arr = [[String]](repeating: [String](repeating: ".", count: 2*n), count: 2*n)
or,
var arr = (0..<2*n).map { _ in [String](repeating: ".", count: 2*n) }
The variable n is only declared, not initialized.
To initialize the variables:
var n: Int = 0
var t: Int = 0

Erroneous data in some cells of tableview

New to scala and scalafx and having an issue with a tableview in a simple stock quote app [note: no prior javafx experience except in ways it is similar to things Android]
Problem: (see image) erroneous data displayed in change column where there should be none.
To create: Multiple scenarios, shown here is entry of new ticker symbol. It seems unpredictable how many cells are in error. Changing window size (say shorter then taller) generally creates more bad cells. Never happens if no change to windowsize and/or symbol list are made.
Code for the 'ticker' and 'change' columns below, though I suspect it is something in how I implemented the change column to do green/red text coloring.
(Note: data is updated in a single batch periodically which is why the new symbol does not immediately display quote data)
val colTicker = new TableColumn[Quote, String] {
editable = true
text = "Ticker"
prefWidth = 80
alignmentInParent = scalafx.geometry.Pos.Center
cellValueFactory = {
_.value.ticker
}
cellFactory = _ => new TextFieldTableCell[Quote, String](new DefaultStringConverter())
onEditCommit = (evt: CellEditEvent[Quote, String]) => {
val quote: Quote = evt.rowValue
val newTickerVal: String = evt.newValue.toUpperCase()
val oldTickerVal: String = evt.oldValue
// is it a valid ticker and not a dupe or is it blank (erase old ticker)?
if ((isValidTicker(newTickerVal) || newTickerVal.length == 0) && !symbolList.contains(newTickerVal)) {
// lock in the new value on the screen
quote.ticker.set(newTickerVal)
// if the new value is not empty add it to symbol list
if (newTickerVal.length > 0) {
symbolList.append(newTickerVal)
}
// now delete the old value
symbolList -= oldTickerVal
// sort and add another blank line
characters.sortWith(_.ticker.getValueSafe < _.ticker.getValueSafe)
if (oldTickerVal.length < 1) characters += Quote()
// now need to update the data file
putListToFile(dataFile, symbolList.sorted)
} else {
// bad ticker so keep the old one and don't update file
quote.ticker.set(oldTickerVal)
evt.getTableView.getColumns.get(0).setVisible(false)
evt.getTableView.getColumns.get(0).setVisible(true)
println("bad ticker, exiting symbol list: " + symbolList)
}
}
}
val colLast = new TableColumn[Quote, String] {
editable = false
text = "Last"
cellValueFactory = {
_.value.last
}
prefWidth = 80
alignmentInParent = scalafx.geometry.Pos.Center
}
val colChange = new TableColumn[Quote, String] {
editable = false
text = "Change"
cellFactory = {
_ =>
new TableCell[Quote, String] {
item.onChange { (_, _, newChange) =>
if (newChange != null) {
if (newChange.toString.contains("+")) textFill = Color.Green
else textFill = Color.Red
text = newChange
}
}
}
}
cellValueFactory = {
_.value.change
}
prefWidth = 80
alignmentInParent = scalafx.geometry.Pos.Center
}
JavaFX is reusing cells when rendering. This is especially noticeable when dynamically updating TableView content. Your cellFactory has to clear cell content when receiving and empty or null item: text and graphic need to be set to null. It may be sufficient to simply check for newChange == null
cellFactory = { _ =>
new TableCell[Quote, String] {
item.onChange { (_, _, newChange) =>
if (newChange == null) {
text = null
graphic = null
else {
if (newChange.toString.contains("+")) textFill = Color.Green
else textFill = Color.Red
text = newChange
}
}
}
}
It that is nor reliable you will have to implement the cellFactory the JavaFX way by implementing javafx.scene.control.TableCell and overwriting method updateItem that is passing in the empty flag:
cellFactory = {_ =>
new javafx.scene.control.TableCell[Quote, String] {
override def updateItem(item: String, empty: Boolean): Unit = {
super.updateItem(item, empty)
if (item == null || empty) {
text = null
graphic = null
}
else {
...
}
}
}
}

How to increment String in Swift

I need to save files in an alphabetical order.
Now my code is saving files in numeric order
1.png
2.png
3.png ...
The problem is when i read this files again I read this files as described here
So I was thinking of changing the code and to save the files not in a numeric order but in an alphabetical order as:
a.png b.png c.png ... z.png aa.png ab.png ...
But in Swift it's difficult to increment even Character type.
How can I start from:
var s: String = "a"
and increment s in that way?
You can keep it numeric, just use the right option when sorting:
let arr = ["1.png", "19.png", "2.png", "10.png"]
let result = arr.sort {
$0.compare($1, options: .NumericSearch) == .OrderedAscending
}
// result: ["1.png", "2.png", "10.png", "19.png"]
If you'd really like to make them alphabetical, try this code to increment the names:
/// Increments a single `UInt32` scalar value
func incrementScalarValue(_ scalarValue: UInt32) -> String {
return String(Character(UnicodeScalar(scalarValue + 1)))
}
/// Recursive function that increments a name
func incrementName(_ name: String) -> String {
var previousName = name
if let lastScalar = previousName.unicodeScalars.last {
let lastChar = previousName.remove(at: previousName.index(before: previousName.endIndex))
if lastChar == "z" {
let newName = incrementName(previousName) + "a"
return newName
} else {
let incrementedChar = incrementScalarValue(lastScalar.value)
return previousName + incrementedChar
}
} else {
return "a"
}
}
var fileNames = ["a.png"]
for _ in 1...77 {
// Strip off ".png" from the file name
let previousFileName = fileNames.last!.components(separatedBy: ".png")[0]
// Increment the name
let incremented = incrementName(previousFileName)
// Append it to the array with ".png" added again
fileNames.append(incremented + ".png")
}
print(fileNames)
// Prints `["a.png", "b.png", "c.png", "d.png", "e.png", "f.png", "g.png", "h.png", "i.png", "j.png", "k.png", "l.png", "m.png", "n.png", "o.png", "p.png", "q.png", "r.png", "s.png", "t.png", "u.png", "v.png", "w.png", "x.png", "y.png", "z.png", "aa.png", "ab.png", "ac.png", "ad.png", "ae.png", "af.png", "ag.png", "ah.png", "ai.png", "aj.png", "ak.png", "al.png", "am.png", "an.png", "ao.png", "ap.png", "aq.png", "ar.png", "as.png", "at.png", "au.png", "av.png", "aw.png", "ax.png", "ay.png", "az.png", "ba.png", "bb.png", "bc.png", "bd.png", "be.png", "bf.png", "bg.png", "bh.png", "bi.png", "bj.png", "bk.png", "bl.png", "bm.png", "bn.png", "bo.png", "bp.png", "bq.png", "br.png", "bs.png", "bt.png", "bu.png", "bv.png", "bw.png", "bx.png", "by.png", "bz.png"]`
You will eventually end up with
a.png
b.png
c.png
...
z.png
aa.png
ab.png
...
zz.png
aaa.png
aab.png
...
Paste this code in the playground and check result. n numbers supported means you can enter any high number such as 99999999999999 enjoy!
you can uncomment for loop code to check code is working fine or not
but don't forget to assign a lesser value to counter variable otherwise Xcode will freeze.
var fileName:String = ""
var counter = 0.0
var alphabets = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
let totalAlphaBets = Double(alphabets.count)
let numFiles = 9999
func getCharacter(counter c:Double) -> String {
var chars:String
var divisionResult = Int(c / totalAlphaBets)
let modResult = Int(c.truncatingRemainder(dividingBy: totalAlphaBets))
chars = getCharFromArr(index: modResult)
if(divisionResult != 0){
divisionResult -= 1
if(divisionResult > alphabets.count-1){
chars = getCharacter(counter: Double(divisionResult)) + chars
}else{
chars = getCharFromArr(index: divisionResult) + chars
}
}
return chars
}
func getCharFromArr(index i:Int) -> String {
if(i < alphabets.count){
return alphabets[i]
}else{
print("wrong index")
return ""
}
}
for _ in 0...numFiles {
fileName = getCharacter(counter: counter)+".png"
print(fileName)
counter += 1
}
fileName = getCharacter(counter: Double(numFiles))+".png"
print(fileName)

Changing an attribute in an object that belongs to RDD

I have the following code :
def generateStoriesnew(outputPath: String, groupedRDD:RDD[(String,Iterable[String])], isInChurnMode: Boolean, isInChurnPeriod: Boolean) {
val windowedRDD = groupedRDD.map(SOME CODE)
var windowedRDD2 = windowedRDD.filter(r => r != null).map(a=>a.churnPeriod(isInChurnPeriod,isInChurnMode))
val prettyStringRDD = windowedRDD2.map(r => {
r.toString
})
prettyStringRDD.saveAsTextFile(outputPath)
}
and here is the code for ChurnPriod function:
def churnPeriod( churnPeriod:Boolean, churnMode: Boolean): Unit = {
if (churnMode && rootEventType.equalsIgnoreCase("c")){
var churnCustStory: CustStoryN = null
var nonChurnCustStory: CustStoryN = null
var churnPeriodEventStory: mutable.MutableList[StoryEventN] = null
var NonChurnEventstory: mutable.MutableList[StoryEventN] = null
churnPeriodEventStory = new mutable.MutableList[StoryEventN]
NonChurnEventstory = new mutable.MutableList[StoryEventN]
var lastEventChurnPeriod = true
var currentEventStory = eventStory
var max = currentEventStory.length
println(max);
if (currentEventStory.size > 0) {
for (i <- 0 until currentEventStory.length) {
var currentEvent = currentEventStory(i)
if (currentEvent.timeSenseRootEvent < 90) {
churnPeriodEventStory.+=(currentEvent)
//lastEventChurnPeriod = true
}
else {
NonChurnEventstory.+=(currentEvent)
lastEventChurnPeriod = false
}
}
}
if (churnPeriod)
eventStory = churnPeriodEventStory
else
eventStory=null
}
}
but churn period function does not change eventstory which is a member of a custstory class. what am I missing here ?
class CustStoryN (val custId:String,
var rootEventType:String,
var rootEventTime:Long,
var eventStory:mutable.MutableList[StoryEventN])
my hypothesis is either:
1.map is not the right transformation for the function that I have
2.churnPeriod function never get called
3.I can not change eventstory which is a member of cust story class
Does anyone have any idea how I can troubleshoot this problem?
This would be trivial to determine by debugging. Just put a few breakpoints and you can see if the program stops inside the function, and what transformations do occur.
My guess would be that the problem is this line: if (currentEventStory.size > 0), thus, a list that starts at size 0 remains at size 0 forever. Another option is that churnPeriod is never true, thus, you compute a lot but never assign to the eventStory variable.
Your code does need a good cleanup ;-)