Convert Number to Corresponding Excel Column [duplicate] - excel

This question already has answers here:
How to convert a column number (e.g. 127) into an Excel column (e.g. AA)
(60 answers)
Closed 8 years ago.
I need some help in doing a logic that would convert a numeric value to corresponding MS Excel header value.
For example:
1 = "A"
2 = "B"
3 = "C"
4 = "D"
5 = "E"
.........
25 = "Y"
26 = "Z"
27 = "AA"
28 = "AB"
29 = "AC"
30 = "AD"
.........
Would appreciate some .NET codes (C# or VB) for this. Thanks.

Here's some VBA (with test code) I strung together in Excel which does the trick. Unless VB.NET has changed drastically, it should work okay. Even if it has, you should be able to translate the idea into workable code.
' num2col - translate Excel column number (1-n) into column string ("A"-"ZZ"). '
Function num2col(num As Integer) As String
' Subtract one to make modulo/divide cleaner. '
num = num - 1
' Select return value based on invalid/one-char/two-char input. '
If num < 0 Or num >= 27 * 26 Then
' Return special sentinel value if out of range. '
num2col = "-"
Else
' Single char, just get the letter. '
If num < 26 Then
num2col = Chr(num + 65)
Else
' Double char, get letters based on integer divide and modulus. '
num2col = Chr(num \ 26 + 64) + Chr(num Mod 26 + 65)
End If
End If
End Function
' Test code in Excel VBA. '
Sub main()
MsgBox ("- should be " & num2col(0))
MsgBox ("A should be " & num2col(1))
MsgBox ("B should be " & num2col(2))
MsgBox ("Z should be " & num2col(26))
MsgBox ("AA should be " & num2col(27))
MsgBox ("AB should be " & num2col(28))
MsgBox ("AY should be " & num2col(51))
MsgBox ("AZ should be " & num2col(52))
MsgBox ("BA should be " & num2col(53))
MsgBox ("ZY should be " & num2col(27 * 26 - 1))
MsgBox ("ZZ should be " & num2col(27 * 26))
MsgBox ("- should be " & num2col(27 * 26 + 1))
End Sub

public string ColumnNumberToLetter(int ColumnNumber)
{
if (ColumnNumber > 26)
{
return ((char) (Math.Floor(((double)ColumnNumber - 1) / 26) + 64)).ToString()
+ ((char) (((ColumnNumber - 1) % 26) + 65)).ToString();
}
return ((char)(ColumnNumber+64)).ToString();
}

Try this:
public static string ToExcelString(int number)
{
if (number > 25)
{
int secondaryCounter = 0;
while (number > 25)
{
secondaryCounter = secondaryCounter + 1;
number = number - 25;
}
return ToExcelChar(number) + ToExcelChar(secondaryCounter);
}
else
{
return ToExcelChar(number)
}
}
private const string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static string ToExcelChar(int number)
{
if (number > 25 || number < 0)
{
throw new InvalidArgumentException("the number passed in (" + number + ") must be between the range 0-25");
}
return alphabet[number];
}

Use a number base conversion routine. You want to convert from base 10 to base 26. Add each digit to 'A'
As in: http://www.vbforums.com/showthread.php?t=271359

Just Use the activecell.address then manuipulate the string based on where the $ is to what you need.

Related

Fastest way to conditionally strip off the right part of a string

I need to remove the numeric part at the end of a string. Here are some examples:
"abcd1234" -> "abcd"
"a3bc45" -> "a3bc"
"kj3ih5" -> "kj3ih"
You get the idea.
I implemented a function which works well for this purpose.
Function VarStamm(name As String) As String
Dim i, a As Integer
a = 0
For i = Len(name) To 1 Step -1
If IsNumeric(Mid(name, i, 1)) = False Then
i = i + 1
Exit For
End If
Next i
If i <= Len(name) Then
VarStamm = name.Substring(0, i - 1)
Else
VarStamm = name
End If
End Function
The question is: is there any faster (more efficient in speed) way to do this? The problem is, I call this function within a loop with 3 million iterations and it would be nice to have it be more efficient.
I know about the String.LastIndexOf method, but I don't know how to use it when I need the index of the last connected number within a string.
You can use Array.FindLastIndex and then Substring:
Dim lastNonDigitIndex = Array.FindLastIndex(text.ToCharArray(), Function(c) Not char.IsDigit(c))
If lastNonDigitIndex >= 0
lastNonDigitIndex += 1
Dim part1 = text.Substring(0, lastNonDigitIndex)
Dim part2 = text.Substring(lastNonDigitIndex)
End If
I was skeptical that the Array.FindLastIndex method was actually faster, so I tested it myself. I borrowed the testing code posted by Amessihel, but added a third method:
Function VarStamm3(name As String) As String
Dim i As Integer
For i = name.Length - 1 To 0 Step -1
If Not Char.IsDigit(name(i)) Then
Exit For
End If
Next i
Return name.Substring(0, i + 1)
End Function
It uses your original algorithm, but just swaps out the old VB6-style string methods for newer .NET equivalent ones. Here's the results on my machine:
RunTime :
- VarStamm : 00:00:07.92
- VarStamm2 : 00:00:00.60
- VarStamm3 : 00:00:00.23
As you can see, your original algorithm was already quite well tuned. The problem wasn't the loop. The problem was Mid, IsNumeric, and Len. Since Tim's method didn't use those, it was much faster. But, if you stick with a manual for loop, it's twice as fast as using Array.FindLastIndex, all things being equal
Given your function VarStamm and Tim Schmelter's one named VarStamm2, here is a small test performance I wrote. I typed an arbitrary long String with a huge right part, and ran the functions one million times.
Module StackOverlow
Sub Main()
Dim testStr = "azekzoerjezoriezltjreoitueriou7657678678797897898997897978897898797989797"
Console.WriteLine("RunTime :" + vbNewLine +
" - VarStamm : " + getTimeSpent(AddressOf VarStamm, testStr) + vbNewLine +
" - VarStamm2 : " + getTimeSpent(AddressOf VarStamm2, testStr))
End Sub
Function getTimeSpent(f As Action(Of String), str As String) As String
Dim sw As Stopwatch = New Stopwatch()
Dim ts As TimeSpan
sw.Start()
For i = 1 To 1000000
f(str)
Next
sw.Stop()
ts = sw.Elapsed
Return String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10)
End Function
Function VarStamm(name As String) As String
Dim i, a As Integer
a = 0
For i = Len(name) To 1 Step -1
If IsNumeric(Mid(name, i, 1)) = False Then
i = i + 1
Exit For
End If
Next i
If i <= Len(name) Then
VarStamm = name.Substring(0, i - 1)
Else
VarStamm = name
End If
End Function
Function VarStamm2(name As String) As String
Dim lastNonDigitIndex = Array.FindLastIndex(name.ToCharArray(), Function(c) Not Char.IsDigit(c))
If lastNonDigitIndex >= 0 Then
lastNonDigitIndex += 1
Return name.Substring(0, lastNonDigitIndex)
End If
Return name
End Function
End Module
Here is the output I got:
RunTime :
- VarStamm : 00:00:38.33
- VarStamm2 : 00:00:02.72
So yes, you should choose his answer, his code is both pretty and efficient.

Truncating 2 Strings and combined into smaller String [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
So, I have two strings that are each a max length of 100.
Dim a as String ''has a max length of 100
Dim b as String ''has a max length of 100
These two strings need to be truncated and combined into a new string.
Dim c as String 'has a max length of 100
I need to be able to truncate each string appropriately so that I can get string c as close to 100. I was going to do a bunch of statements by 25 to truncate each one.
if a.length = 100 and b.length =0 then
return a
else if a.length = 100 andalso b.length <= 25 then
return a.truncate(75) & b
else if a.length = 100 andalso b.length <= 50 then
return a.truncate(50) & b
else if....
and so one to hit all the scenarios...
I feel like there is a better way to do this and a more efficient way so that i may not hit scenarios like a.length = 100 and b.length = 51. I would be truncating more characters then needed.
Any suggestions?? Please critique me as needed.
EDIT, This is vb.Net..not C# (I'm between Projects) Sorry!
The reason i do not want to just add them together and truncate them is because if both strings are 100 in length, it will completely truncate off the second string. If they are both 100 then I would want to truncate string a to 50 in length and string b to 50 in length so when they are combined they are 100 total. In other words I need some text from both strings.
If the total length of the strings is greater than the limit then you could take a fraction of each in proportion to their lengths:
Module Module1
Function CombineWithLengthConstraint(a As String, b As String, totalLength As Integer) As String
' trivial case 1:
If totalLength < 1 Then
Return String.Empty
End If
Dim aLen = Len(a)
Dim bLen = Len(b)
' trivial case 2:
If aLen + bLen <= totalLength Then
Return a & b
End If
' impossible-to-satisfy-equably case:
If totalLength = 1 Then
If aLen > 0 Then
Return a.Substring(0, 1)
ElseIf bLen > 0 Then
Return b.Substring(0, 1)
Else
Return String.Empty
End If
End If
' aportion the lengths of the strings to be taken in the ratio of their lengths:
Dim aFrac = CInt(Math.Round(aLen / (aLen + bLen) * totalLength, MidpointRounding.AwayFromZero))
Dim bFrac = CInt(Math.Round(bLen / (aLen + bLen) * totalLength, MidpointRounding.AwayFromZero))
' ensure there is at least one character from each string...
If aFrac = 0 Then
aFrac = 1
bFrac -= 1
End If
If bFrac = 0 Then
bFrac = 1
aFrac -= 1
End If
Dim aPart = a.Substring(0, aFrac)
Dim bPart = b.Substring(0, bFrac)
Return aPart & bPart
End Function
Sub Main()
Dim a = New String("A"c, 10)
Dim b = New String("b"c, 40)
Dim c = CombineWithLengthConstraint(a, b, 10)
Console.WriteLine(c)
Console.WriteLine(Len(c))
Console.ReadLine()
End Sub
End Module
Outputs:
AAbbbbbbbb
10
As you can see, the first string, which was 1/5 of the total number of characters, ended up contributing 1/5 of the result.
The VB.NET Len function gives 0 if its argument is Nothing.
I tested it as working with all lengths from 0 to 100 of both strings being combined into one string of length 100 just in case I had made a mistake with the rounding or anything.
Of course, you could return, say, the ending part of string b instead of the starting part if that made sense in the particular application.
Although not exactly what you asked for, here's another option...
Public Function WeirdConcatinate(a As String, b As String) As String
Dim totalLen = a.Length + b.Length
If totalLen > 100 Then
Dim aLen = 100 * a.Length \ totalLen
Dim bLen = 100 - aLen
Return a.Remove(aLen) & b.Remove(bLen)
Else
Return a & b
End If
End Function
This will give you a number of characters from each string (approximately) proportional to how long they are compared to each other. If both strings are the same length, you'll get 50 from each. If a.Length = 100 and b.Length = 50, you'll end up with 66 from a and 34 from b.
Truncate them after concatenating them, then:
Dim c = a & b
If c.Length > 100 Then c = c.Remove(100)
If you want to preserve as much as possible of the start of each string:
Dim c = ""
If(a.Length > 50 AndAlso b.Length < 50)
c = a.Remove(100 - b.Length) & b
Else If a.Length > 50 AndAlso b.Length > 50
c= a.Remove(50) & b.Remove(50)
Else
c = a & b
End if
If c.Length > 100 Then c = c.Remove(100)
As with some other answers, the algorithm is open to interpretation. My method takes from each string until 100 total characters are taken or the string runs out of characters.
Private Function concat(a As String, b As String, length As Integer) As String
Dim ca As New System.Text.StringBuilder()
Dim cb As New System.Text.StringBuilder()
For i As Integer = 0 To length - 1
ca.Append(If(i >= a.Length, "", a(i)))
cb.Append(If(i >= b.Length, "", b(i)))
If ca.Length + cb.Length >= length Then Exit For
Next
Return (ca.ToString() & cb.ToString() & New String(" "c, 100)).Substring(0, length)
End Function
Sub Main()
Dim a As String = New String("a"c, 0)
Dim b As String = New String("b"c, 5)
Dim c As String = concat(a, b, 100)
Console.WriteLine($"'{c}'")
End Sub
'bbbbb '
(padded to 100 characters, doesn't render in block quote)
Dim a As String = New String("a"c, 30)
Dim b As String = New String("b"c, 90)
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'
Dim a As String = New String("a"c, 72)
Dim b As String = New String("b"c, 64)
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'
(your example in a comment. 72 >> 50, 64 >> 50)

VBScript string replace with range instead of string?

Replace() already exists, but that function takes strings as parameters. I need range.
In my string there are two "strings" that are 10 characters long.
Greger with 6 chars and 4 spaces and the other string with 10 characters.
"Greger AASSDDFFGG"
I want to replace "Greger " with "googlioa "
What i'm looking for is basically this:
Replace(MyString,1,10) = "googlioa "
Is there any way to achieve this?
If they're always going to be 10 chars, just pad the names.
strNameFind = "Greger"
strNameReplace = "googlioa"
' Pad the names...
strNameFind = Left(strNameFind & Space(10), 10)
strNameReplace = Left(strNameReplace & Space(10), 10)
MyString = Replace(MyString, strNameFind, strNameReplace)
Alternatively, if you don't want to determine the existing name, just pad your new name appropriately and add the remainder of your string:
' Pad the new name to fit in a 10-char column...
strNameReplace = "googlioa"
strNameReplace = Left(strNameReplace & Space(10), 10)
' Update the record...
MyString = strNameReplace & Mid(MyString, 11)
If you want to replace strictly by position, use concatenation of Left(), new, and Mid(). To get you started:
>> Function replByPos(s, f, l, n)
>> replByPos = Left(s, f-1) & n & Mid(s, f + l - 1)
>> End Function
>> s = "Greger AASSDDFFGG"
>> r = replByPos(s, 1, 10, "googlioa ")
>> WScript.Echo s
>> WScript.Echo r
>>
Greger AASSDDFFGG
googlioa AASSDDFFGG
>>
Further enhancements:
safety: f(rom) - 1 is risky - should be checked
padding of new string wrt l(ength)
perhaps you want to search (Instr()) for old ("Greger ") before the concatenation
On second thought (and stealing Bond's padding):
Maybe I should have interpeted the 10 as a to/till/upto value instead of a length/width specification. So see whether
Option Explicit
Function replByPos(src, from, till, ns)
Dim w : w = till - from
replByPos = Left(src, from - 1) & Left(ns & Space(w), w) & Mid(src, till)
End Function
Dim s : s = "Greger AASSDDFFGG"
Dim ns : ns = "googlioa"
WScript.Echo s
WScript.Echo replByPos(s, 1, 10, ns)
s = "Whatever Greger AASSDDFFGG"
ns = "googlioa"
Dim p : p = Instr(s, "Greger")
WScript.Echo s
WScript.Echo replByPos(s, p, p + 10, ns)
output:
cscript 22811896.vbs
Greger AASSDDFFGG
googlioa AASSDDFFGG
Whatever Greger AASSDDFFGG
Whatever googlioa AASSDDFFGG
matches your specs better.

Who owes who money algorithm in excel spreadsheet

I have a group of people who have different expenses during a period. Everybody has a balance after this period. It looks like this in excel:
Person A: 6
Person B: 10
Person C: -7,5
Person D: -8,5
After this period a settlement will take place. I currently do this by manually. This results in:
Person C pays 6 to person A.
Person C pays 1,5 to person B.
Person D pays 8,5 to person B.
Person A gets 6 from person C.
Person B gets 1,5 form person C.
Peron B gets 8,5 from person D.
(There are multiple solutions possible when more persons are involved.)
The problem is that I have to apply this procedure for a big group of people. So my question is: 'How to apply this 'who owes who'-procedure by using an excel spreadsheet algorithm or macro?'.
I made a excel version too but its in Open office. can you download that? The following macro might work on its own. If it does not should be something small. it works fine in OOO and is saved as a Excel 97/2000 workbook document.
'this might not be needed in Microsoft Excel, comment it out
Option VBASupport 1 'OWES
Option Explicit
'Cells(row, col),
Private Sub cmd1_Click()
'data is same sheet, from row 4, column 4
'row 4 has names in columns, so 4,4 has name 1, 4,5 has name 2
'row 5 has amounts spent like 6, -10
'output is in columns 3 and 5
dim i
dim j,s as String, sum1
s=""
'get number of cells used in row 4 and check if corresponding row 6 column has a number value too
i = 4
sum1=0
do while(cells(4,i).Value <> "" and i < 500)
j = CDbl(cells(5,i).Value)
sum1 = sum1 + j
if j <> cells(5,i).Value then
MsgBox "Col " & i & " not a number?"
End
end if
i=i+1
loop
if i > 499 then
Msgbox "too many cols"
End
end if
If sum1 > 0.3 or sum1 < -0.3 then
Msgbox "Sum is not near 0 :" & sum1
End
End if
Dim colCnt as Integer
colCnt = i - 4
cells (7,1).Value = "Col count = " & colCnt
Dim spent(colCnt) as Double
Dim owes1(colCnt ) as String
Dim owes2(colCnt ) as String
for i= 4 to colCnt + 3
spent(i - 3) = CDbl(cells(5,i).Value)
Next
Dim cnt,lastNeg, abs1,maxPay ' safety var for never ending loops, only if data bad like many cols and more than .1 diffs
lastNeg = 4
dim lastPay1
lastPay1 = 10
dim ii,jj,c1,c2,toPay
toPay = 0
On Local Error Goto errh
for i= 4 to colCnt + 3
cnt = 0
ii = i - 3
c1 = spent(ii)
'Cells(6,i) = "ok "
if spent(ii) > 0.1 and cnt < colCnt Then '//has to take
cnt = cnt + 1
for j = lastNeg to colCnt + 3 ' ; j < people.length && spent(ii) > 0.1; j++)
jj = j - 3
's = s & Me.Cells(ii,j) & " "
if spent(ii) > 0.1 then
if spent(jj) < -0.1 Then ' //has to give and has balance to give
c1 = spent(ii)
c2 = spent(jj)
lastNeg = j
abs1 = spent(jj) * -1'//can use absolute fn
maxPay = abs1
if(maxPay > spent(ii)) Then
toPay = spent(ii)'
else
toPay = abs1
End if
spent(ii) = spent(ii) - toPay
spent(jj) = spent(jj) + toPay
Cells(lastPay1, 3).Value = Cells(4 , j) & " pays " & toPay & " to " & Cells(4 , i )
Cells(lastPay1, 5).Value = Cells(4 , i) & " gets " & toPay & " from " & Cells(4 , j)
lastPay1 = lastPay1 + 1
End if
End if
Next
End if
Next
Msgbox "Done"
err.Clear
if err.Number <> 0 Then
errH:
dim yy
yy = msgBox("err " & err.Number & " " & err.Description & " Continue", 2)
if yy = vbYes Then
Resume Next
End IF
End IF
End Sub
Book at http://sel2in.com/prjs/vba/profile (owes)
Can see http://www.excel-vba.com/ , http://office.microsoft.com/en-in/training/get-in-the-loop-with-excel-macros-RZ001150634.aspx the help in excel was useful too (f1 inside macro editor, can select a keyword or type and get context sensitive help by pressing f1)
How important is the pairing of who owes what to who? The reason I ask - it's simple to figure out the total cost per person and then determine who owes money and who needs a refund. If one person can be the "banker", he can collect all the money due and disburse all the refunds.
Much simpler question, if you have somebody willing to be the banker.
Trying to pair everything up will quite possibly not result in an exact answer, or may require one or more people making payments to more than one person - as well as one or more people trying to collect from more than one other person.
See http://sel2in.com/pages/prog/html/owes.html
Javascript fn
<form>
Paste tab seperated list of people on first line, Second line has blanace - positive means they spent more than others, negative means other spent on them (they owe)
<br>
<textarea id=t1 rows=3 cols=70></textarea>
</form>
<button onclick=calcOwes() >Calc owes</button>
<br>
<b>Result:</b>
<div id=result>Will appear here if data is good</div>
<br>
<b>Parsed data for debug:</b>
<div id=data1>Will appear here if data is good</div>
<br>
<hr>
<script>
function calcOwes(){
/**
2013 Tushar Kapila
If Person A: 6
Person B: 10
Person C: -7,5
Person D: -8,5
Then Person C pays 6 to person A.
Person C pays 1,5 to person B.
Person D pays 8,5 to person B.
*/
s = document.getElementById("t1").value
var line = s.split("\n")
//v = confirm("Your Data looks okay?:\n" + s)
//if(!v){ return;}
if(s.length < 2 || s.indexOf("\n") < 0){
alert("No line sep ")
return
}
people = line[0].split("\t")
spent = line[1].split("\t")
spent2 = line[1].split("\t")
if(spent.length < 2){
alert("Bad data, no spent data " + spent.length + "; 0 " + spent[0] + "; 1 " + + spent[1])
return
}
if(people.length != spent.length){
alert("People and amounts do not tally. make sure no tabs inside names, spaces are okay")
return
}
sum = 0;
data1o = document.getElementById("data1")
data1o.innerHTML = "";
for(i = 0;i < people.length; i++){
spent[i] = spent[i].trim()
spent[i] = parseFloat(spent[i])
sum += spent[i]
s = (1 + i) + " \"" + people[i] + "\" :" + spent[i] + ";<br>"
data1o.innerHTML += s;
}
if(sum > 0.2 || sum < -0.2){
v = confirm("Sum (" + sum + ")is not zero continue?")
if(!v){return;}
}
lastNeg = 0;
payDetails = new Array();
getDetails = new Array();
lastPay = 0;
for(i = 0;i < people.length; i++){
cnt = 0;
if(spent[i] > 0.1 && cnt < people.length){//has to take
cnt++
for(j = lastNeg; j < people.length && spent[i] > 0.1; j++){
if(spent[j] < -0.1){//has to give and has balance to give
lastNeg = j;
abs1 = spent[j] * -1;//can use absolute fn
maxPay = abs1
if(maxPay > spent[i]){
toPay = spent[i];
}else{
toPay = abs1
}
spent[i] -= toPay
spent[j] += toPay
payDetails[lastPay] = people[j] + " pays " + toPay + " to " + people[i]
getDetails[lastPay] = people[i] + " gets " + toPay + " from " + people[j]
lastPay++;
}
}
}
}
s = ""
s2 = ""
for(i = 0;i < lastPay; i++){
s = s + payDetails[i] + "<br>"
s2 = s2 + getDetails[i] + "<br>"
}
document.getElementById("result").innerHTML = s + "<br>" + s2
}
</script>
<br>Sample input 1 (tabs there?)
<br><pre>
a b c d
6 10 -7.5 -8.5
</pre>
<br>Sample input 2
<pre>
Anna Dan Bobby Scareface Colly Doc Egg face
-6 10 -7.3 -8.33 11.67
</pre>

Why am I getting incorrect values for string length?

My professor is teaching us Scala using Horstmann's book "Scala for the impatient", and one of our homework exercises are straight from the book; Chapter 4, exercise 2.
We are expected to read in the eBook in text format, the professor has specified that the input file should be "Moby Dick", available for free from the Guttenberg project here: http://www.gutenberg.org/ebooks/2701.txt.utf-8
My code works, as far as counting instances of words. However, he has added the requirement that we must we must format the output in two two columns, with words left justified, and counts right justified. To do so, I am determining the longest word in the book so I can figure the width of the "word" column. However, the values I am getting for the length of the strings is just wrong. In fact, it tells me that all the strings are the same length. "a" is being reported as length 26, just as is "Whale", "Ishmael", etc...
Here's the code:
object Chapter4Exercise2 extends App {
//for sorting
import util.Sorting._
//grab the file
val inputFile = new java.util.Scanner(new java.io.File("moby.txt"))
//create a mutable map where key/values == word/count
val wordMap = collection.mutable.Map[String, Int]() withDefault (_ => 0)
//for formatting output (later), the longest word length is relevant
var longestWord = 0
var theWord: String = ""
//start reading each word in the input file
while (inputFile hasNext) {
//grab the next word for processing, convert it to lower case, trim spaces and punctuation
var nextWord = inputFile.next().toLowerCase().trim().filter(Character.isLetter(_))
//if it's the longest word, update both theWord and longestWord
if (nextWord.size > longestWord) longestWord = nextWord.size; theWord = nextWord; println(theWord + " " + longestWord)
//update the map value for the key with same value as nextWord
wordMap(nextWord) += 1
}
println("Longest word is " + theWord + " at " + longestWord + " Characters")
}
The output of these lines:
if (nextWord.size > longestWord) longestWord = nextWord.size; theWord = nextWord; println(theWord + " " + longestWord)
and
println("Longest word is " + theWord + " at " + longestWord + " Characters")
is way off. It's telling me that EVERY word in the input file is 26 characters long!
Here's a small sample of what's being output:
husks 26
on 26
a 26
surfbeaten 26
beach 26
and 26
then 26
diving 26
down 26
into 26
What am I missing/doing wrong?
if (nextWord.size > longestWord) longestWord = nextWord.size; theWord = nextWord; println(theWord + " " + longestWord)
You shouldn't write multiple statements on a single line like that. Let's write this out in multiple lines and properly indent it:
if (nextWord.size > longestWord)
longestWord = nextWord.size
theWord = nextWord
println(theWord + " " + longestWord)
Do you see the problem now?
Try putting { and } around your if statement alternatives.
You can avoid this kind of pitfall by formatting your code in a structured manner - always using braces around code blocks.
if (nextWord.size > longestWord)
{
longestWord = nextWord.size;
theWord = nextWord;
println(theWord + " " + longestWord);
}
Your current code is equivalent to
if (nextWord.size > longestWord)
{
longestWord = nextWord.size;
}
theWord = nextWord;
println(theWord + " " + longestWord);

Resources