Reply
 
Thread Tools Display Modes
Old 12-18-12, 10:32 AM   #1
Aanson
A Flamescale Wyrmkin
Join Date: Aug 2009
Posts: 123
Dividing hundreds and thousands by a comma

Hi again all!

This isn't really too essential, and I'm maybe just being a bit too picky here, but is there any way to do the following:

Convert 123123 to 123,123 ?

I created the following function for use on the AUCTION_HOUSE_CLOSED event:

Lua Code:
  1. M.GetData_CalculateListingValue = function()
  2.     local announce = C.GetActiveProfile().Modules[module].sayListingValueOnClose;
  3.     if (not announce) then return nil; end
  4.     local value = 0;
  5.     local pageAuctions, totalAuctions = GetNumAuctionItems("owner");
  6.     for i = 1, totalAuctions do
  7.         value = ( value + select(10, GetAuctionItemInfo("owner", i)) );
  8.     end
  9.     if (value > 0) then
  10.         return GetCoinTextureString(value);
  11.     end
  12.     return nil;
  13. end

I've discovered though that GetCoinTextureString() returns the number format described above. I've tried my hand at using string.format but I've not had any luck so far.


One other completely unrelated question while I'm here. When a variable is expressed within a function (for example "announce" in the function above; I understand it to be local to that function only. What I'm not sure of though is, what if I omitted the 'local'? Would it become a Global and pollute the global namespace, or will it still be local only to that function?

Also, what about this example?:

Lua Code:
  1. M.GetData_CalculateListingValue = function(announce)
  2. local announce = (announce or false);
  3. -- doing stuff with announce
  4. end

Am I still required to prefix 'announce' with 'local' or should I not be doing that?

Thanks in advance for any help you guys could give with this.
__________________
__________________
Aanson is offline   Reply With Quote
Old 12-18-12, 12:40 PM   #2
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 9,529
If you take away the "local", then yes - it will be a global. Unless you declare that variable as local in your upvalues (outside of the function, therefore local to your whole Lua file.)
__________________
"You'd be surprised how many people violate this simple principle every day of their lives and try to fit square pegs into round holes, ignoring the clear reality that Things Are As They Are." -Benjamin Hoff, The Tao of Pooh

Seerah is offline   Reply With Quote
Old 12-18-12, 01:05 PM   #3
Torhal
A Pyroguard Emberseer
 
Torhal's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2008
Posts: 1,026
Blizzard's build-in UI function BreakUpLargeNumbers() does what you need.
__________________
Whenever someone says "pls" because it's shorter than "please", I say "no" because it's shorter than "yes".

Author of Revelation, Spamalyzer, TravelAgent, Volumizer, and many other AddOns.
Torhal is offline   Reply With Quote
Old 12-18-12, 01:42 PM   #4
SDPhantom
A Molten Giant
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 943
Unfortunately, BreakUpLargeNumbers() only works on number values, not strings such as one returned by GetCoinTextureString(). The following code will try to reformat an already formatted string. Note, don't try to use this on strings that contain numbers with a decimal component.

Lua Code:
  1. function ReformatNumberString(str)
  2.     local repstr="%1"..LARGE_NUMBER_SEPERATOR.."%2";
  3.  
  4. --  Initial replacement of a number group at the end of the string
  5.     str=str:gsub("(%d)(%d%d%d)$",repstr));
  6.  
  7. --  Note repeat checks post-loop, unlike while that checks pre-loop
  8. --  This not only guarantees the loop code to run at least once before the condition is checked, but allows use of locals inside the loop for the condition
  9.     repeat
  10. --      Writing to an upvalue actually uses one additional opcode from just reregistering a local inside a loop
  11.         local numrep;
  12.  
  13. --      Looping replacement of a number group followed by a non-number
  14.         str,numrep=str:gsub("(%d)(%d%d%d%D)",repstr));
  15.     until numrep<=0
  16. end
__________________
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 12-18-12 at 01:52 PM.
SDPhantom is offline   Reply With Quote
Old 12-18-12, 04:12 PM   #5
Aanson
A Flamescale Wyrmkin
Join Date: Aug 2009
Posts: 123
Originally Posted by Seerah View Post
If you take away the "local", then yes - it will be a global. Unless you declare that variable as local in your upvalues (outside of the function, therefore local to your whole Lua file.)
Thanks all.

So with this example, just so I've got it straight in my head:

Lua Code:
  1. M.GetData_CalculateListingValue = function(announce)
  2.     announce = (announce or false);
  3.     -- doing stuff with announce
  4. end

The function argument 'announce' will now be a global because it wasn't declared local within the function?
__________________
__________________
Aanson is offline   Reply With Quote
Old 12-18-12, 04:17 PM   #6
Torhal
A Pyroguard Emberseer
 
Torhal's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2008
Posts: 1,026
No. In your example, "announce" is a parameter which is passed in from elsewhere, so it is either already global or local to the scope from whence it originated. Also, the line:

Code:
announce = (announce or false)
...is usually semantically identical to saying "This boolean value is either what it already equates to or false" unless you really need to differentiate between "false" and "nil".
__________________
Whenever someone says "pls" because it's shorter than "please", I say "no" because it's shorter than "yes".

Author of Revelation, Spamalyzer, TravelAgent, Volumizer, and many other AddOns.
Torhal is offline   Reply With Quote
Old 12-19-12, 04:28 AM   #7
SDPhantom
A Molten Giant
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 943
To further clarify, function arguments are treated as local variables and only exist within the scope of the function itself.
__________________
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
SDPhantom is offline   Reply With Quote
Old 12-19-12, 02:24 PM   #8
Farmbuyer
A Cyclonian
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 43
Originally Posted by Aanson View Post
Convert 123123 to 123,123 ?
This has been floating around a long time, I can't take credit for it. Optimizations and input checking is left as an exercise for the future googler.

Code:
function comma (str)
    str = tostring(str)   // now you can feed it numbers instead of strings
    local prefix, number, suffix = str:match"(%D*%d)(%d+)(%D*)"
    return prefix .. number:reverse():gsub("(%d%d%d)","%1,"):reverse() .. suffix
end

print(comma("300"))
print(comma("300g"))
print(comma("-1234g"))
print(comma("$42424242US"))

Last edited by Farmbuyer : 12-19-12 at 02:29 PM. Reason: handle direct numerical input
Farmbuyer is offline   Reply With Quote
Old 12-19-12, 03:01 PM   #9
Clamsoda
A Cobalt Mageweaver
Join Date: Nov 2011
Posts: 239
I found this function while browsing the WoWAce forums. I believe the credit goes to Phanx, but I don't think the post explicitly stated that she wrote it.

Lua Code:
  1. local function numformat(num)
  2.     if not num then return 0 end
  3.     if abs(num) < 1000 then return num end
  4.     local neg = num < 0 and "-" or ""
  5.     local left, mid, right = tostring(abs(num)):match("^([^%d]*%d)(%d*)(.-)$")
  6.     return ("%s%s%s%s"):format(neg, left, mid:reverse():gsub("(%d%d%d)", "%1,"):reverse(), right)
  7. end

Only works for whole numbers apparently.
Clamsoda is offline   Reply With Quote
Old 12-19-12, 08:16 PM   #10
SDPhantom
A Molten Giant
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 943
Scroll up to my post above, should be #4. Unlike the code posted in the last couple posts, the one I wrote should work specifically on GetCoinTextureString(). This is because the pattern matching works on ALL numbers in the string, not just a random one of the group.
__________________
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 12-19-12 at 08:21 PM.
SDPhantom is offline   Reply With Quote
Old 12-19-12, 08:59 PM   #11
SDPhantom
A Molten Giant
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 943
I came up with a little more complex code. This should handle decimal numbers and still support reformatting multiple numbers in a string. It works by nesting string:gsub() calls in replacement functions. The base function seeks out all numbers and calls SplitDecimal() to modify them. SplitDecimal()'s entire purpose is for decimal number support and will only grab the integer section of a decimal number, calling AddCommas() on it and leaving the rest alone. AddCommas() is what inserts the locale-dependent separator as stored in LARGE_NUMBER_SEPERATOR. This global is what's used in the Default UI code for BreakUpLargeNumbers().
Lua Code:
  1. local ReformatNumberString; do
  2.     local AddCommas(pre,post) return pre..post:reverse():gsub("(%d%d%d)","%1"..LARGE_NUMBER_SEPERATOR):reverse(); end
  3.     local SplitDecimal(str) return str:gsub("^(%d)(%d+)",AddCommas); end
  4.     function ReformatNumberString(str) return str:gsub("[%d%.]+",SplitDecimal); end
  5. end
__________________
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
SDPhantom is offline   Reply With Quote
Old 12-20-12, 05:09 AM   #12
Aanson
A Flamescale Wyrmkin
Join Date: Aug 2009
Posts: 123
Originally Posted by SDPhantom View Post
I came up with a little more complex code. This should handle decimal numbers and still support reformatting multiple numbers in a string. It works by nesting string:gsub() calls in replacement functions. The base function seeks out all numbers and calls SplitDecimal() to modify them. SplitDecimal()'s entire purpose is for decimal number support and will only grab the integer section of a decimal number, calling AddCommas() on it and leaving the rest alone. AddCommas() is what inserts the locale-dependent separator as stored in LARGE_NUMBER_SEPERATOR. This global is what's used in the Default UI code for BreakUpLargeNumbers().
Lua Code:
  1. local ReformatNumberString; do
  2.     local AddCommas(pre,post) return pre..post:reverse():gsub("(%d%d%d)","%1"..LARGE_NUMBER_SEPERATOR):reverse(); end
  3.     local SplitDecimal(str) return str:gsub("^(%d)(%d+)",AddCommas); end
  4.     function ReformatNumberString(str) return str:gsub("[%d%.]+",SplitDecimal); end
  5. end
Thanks very much everyone for going out of your way to help.

Special thanks to Phantom... i'll give that code a wee try today

Aanson
__________________
__________________
Aanson is offline   Reply With Quote
Reply

Go BackWoWInterface » Developer Discussions » Lua/XML Help » Dividing hundreds and thousands by a comma

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off