For the below input:
INPUT1 = "0.00|0.00|0.00|0.00|0.00|0.00|0.00||0.10";
INPUT2 = "404,671.00|0.00|0.00|417,975.64|0.00|0.00|417,353.81|0.00|0.00|418,338.38|0.00|0.00|418,908.39||";
INPUT3 = "404,671.00|0.00|0.00|417,975.64|0.00|0.00|417,353.81|0.00|0.00|418,338.38|0.00|0.00|418,908.39";
INPUT4 = "20,500,000.00|20,500,000.00|20,500,000.00|20,500,000.00|20,500,000.00|20,500,000.00|20,500,000.00|20,500,000.00|20,500,000.00";
INPUT5 = "20181221|20181227|20190128|20190227|20190327|20190429|20190528|20190627|20190729|20190827|20190927|20191028|20191127|20191227|20200127|20200227";
Output Should be like below:
#No|input5|input4|input2|input1|input3
1|20181221|20,500,000.00|404,671.00|0.00|404,671.00
2|20181227|20,500,000.00|0.00|0.00|0.00
.......
Tried in traditional (old way). But, implementation should be in Java 8.
public class FormatterDemo {
public static String INPUT1 = "0.00|0.00|0.00|0.00|0.00|0.00|0.00||0.10";
public static String INPUT2 = "404,671.00|0.00|0.00|417,975.64|0.00|0.00|417,353.81|0.00|0.00|418,338.38|0.00|0.00|418,908.39||";
public static String INPUT3 = "404,671.00|0.00|0.00|417,975.64|0.00|0.00|417,353.81|0.00|0.00|418,338.38|0.00|0.00|418,908.39";
public static String INPUT4 = "20,500,000.00|20,500,000.00|20,500,000.00|20,500,000.00|20,500,000.00|20,500,000.00|20,500,000.00|20,500,000.00|20,500,000.00";
public static String INPUT5 = "20181221|20181227|20190128|20190227|20190327|20190429|20190528|20190627|20190729|20190827|20190927|20191028|20191127|20191227|20200127|20200227";
public static String REGEX_PATTERN = "\\|";
public static void main(String[] args) {
String[] input1SplitStr = INPUT1.split(REGEX_PATTERN);
String[] input2SplitStr = INPUT2.split(REGEX_PATTERN);
String[] input3SplitStr = INPUT3.split(REGEX_PATTERN);
String[] input4SplitStr = INPUT4.split(REGEX_PATTERN);
String[] input5SplitStr = INPUT5.split(REGEX_PATTERN);
int maxSizeValue = findMaxValue(input1SplitStr.length, input2SplitStr.length, input3SplitStr.length,
input4SplitStr.length, input5SplitStr.length);
for (int i = 1; i <= maxSizeValue; i++) {
String input5Value = (i <= input5SplitStr.length && input5SplitStr[i - 1] != null)
? input5SplitStr[i - 1]
: "";
String input4Value = (i <= input4SplitStr.length && input4SplitStr[i - 1] != null)
? input4SplitStr[i - 1]
: "";
String input2Value = (i <= input2SplitStr.length && input2SplitStr[i - 1] != null)
? input2SplitStr[i - 1]
: " ";
String input1Value = (i <= input1SplitStr.length && input1SplitStr[i - 1] != null)
? input1SplitStr[i - 1]
: " ";
String input3Value = (i <= input3SplitStr.length && input3SplitStr[i - 1] != null)
? input3SplitStr[i - 1]
: " ";
System.out.println(i + "|" + input5Value + "|" + input4Value + "|" + input2Value + "|" + input1Value
+ "|" + input3Value);
}
}
private static int findMaxValue(int... lengths) {
int maxLength = Integer.MIN_VALUE;
for (int i : lengths) {
if (i > maxLength) {
maxLength = i;
}
}
return maxLength;
}
}
Expected/current output:
No|input5|input4|input2|input1|input3
1|20181221|20,500,000.00|404,671.00|0.00|404,671.00
2|20181227|20,500,000.00|0.00|0.00|0.00
3|20190128|20,500,000.00|0.00|0.00|0.00
4|20190227|20,500,000.00|417,975.64|0.00|417,975.64
5|20190327|20,500,000.00|0.00|0.00|0.00 .
.........
This is the traditional way I implemented.
Help would be appreciated to do in java 8
I think it could be smth. like this one:
List<String[]> data = Stream.of(INPUT5, INPUT4, INPUT3, INPUT2, INPUT1)
.map(in -> in.split(REGEX_PATTERN))
.collect(Collectors.toList());
IntSupplier getMaxLength = () -> data.stream().mapToInt(arr -> arr.length).max().orElse(0);
BiFunction<String[], Integer, String> valueAt = (arr, i) -> Optional.ofNullable(i < arr.length ? arr[i] : null).orElse("");
List<String> lines = IntStream.range(0, getMaxLength.getAsInt())
.mapToObj(i -> {
Stream<String> s1 = Stream.of(String.valueOf(i + 1));
Stream<String> s2 = data.stream().map(arr -> valueAt.apply(arr, i));
return Stream.concat(s1, s2).collect(Collectors.joining("|"));
}).collect(Collectors.toList());
lines.forEach(System.out::println);
Related
i already able to print text using kotlin to thermal printer, but im still dont know how to print image to thermal printer in kotlin. please give me sample printing image to thermal printer in kotlin.i already search for the topics, but it written in java, i doesnt know java very much thanks for the help
private fun p1() {
val namaToko = "Rose Medical"
val alamatToko = "Pramuka raya no.1 Jakarta Timur"
val telp = "021-85901642"
val enter = "\n"
val strip = "-"
val rp ="Rp."
val ex = " X "
val textTotal = "Total Rp:"
val ppnTv = "PPN :Rp."
val chargeTv ="Charge :Rp."
val totalTv = "Total Belanja :Rp."
val scope = CoroutineScope(Dispatchers.IO)
scope.launch {
// chunks1
try{
writeWithFormat(namaToko.toByteArray(),Formatter().get(),Formatter.centerAlign())
writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign())
writeWithFormat(alamatToko.toByteArray(),Formatter().get(),Formatter.centerAlign())
writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign())
writeWithFormat(telp.toByteArray(),Formatter().get(),Formatter.centerAlign())
writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign())
writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign())
}catch (e: Exception) {
Log.e("PrintActivity", "Exe ", e)
}
// chunks2
for(pointer in salesBody.indices){
try {
val merk = salesBody[pointer].merk
writeWithFormat(merk!!.toByteArray(),Formatter().get(),Formatter.leftAlign())
writeWithFormat(strip.toByteArray(),Formatter().get(),Formatter.leftAlign())
val barang = salesBody[pointer].namaBrg
writeWithFormat(barang!!.toByteArray(),Formatter().get(),Formatter.leftAlign())
writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign())
val varian = salesBody[pointer].varian
writeWithFormat(varian!!.toByteArray(),Formatter().get(),Formatter.leftAlign())
writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign())
writeWithFormat(rp.toByteArray(),Formatter().get(),Formatter.leftAlign())
val harga = ValidNumber().deciformat(salesBody[pointer].hargaJual.toString())
writeWithFormat(harga.toByteArray(),Formatter().get(),Formatter.leftAlign())
writeWithFormat(ex.toByteArray(),Formatter().get(),Formatter.leftAlign())
val jumlah = ValidNumber().deciformat(salesBody[pointer].qty.toString())
writeWithFormat(jumlah.toByteArray(),Formatter().get(),Formatter.leftAlign())
val satuan = salesBody[pointer].unit
writeWithFormat(satuan!!.toByteArray(),Formatter().get(),Formatter.leftAlign())
writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign())
writeWithFormat(textTotal.toByteArray(),Formatter().get(),Formatter.rightAlign())
val total = ValidNumber().deciformat(salesBody[pointer].total.toString())
writeWithFormat(total.toByteArray(),Formatter().get(),Formatter.leftAlign())
writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign())
}catch (e: Exception) {
Log.e("PrintActivity", "Exe ", e)
}
}
// chunks3
try{
writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign())
val tanggal = salesHeader[0].tanggal
writeWithFormat(tanggal!!.toByteArray(),Formatter().get(),Formatter.leftAlign())
writeWithFormat(strip.toByteArray(),Formatter().get(),Formatter.leftAlign())
val jam = salesHeader[0].jam
writeWithFormat(jam!!.toByteArray(),Formatter().get(),Formatter.leftAlign())
writeWithFormat(strip.toByteArray(),Formatter().get(),Formatter.leftAlign())
val idTag= salesHeader[0].idTag
writeWithFormat(idTag!!.toByteArray(),Formatter().get(),Formatter.leftAlign())
writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign())
val payment= salesHeader[0].payment
writeWithFormat(payment!!.toByteArray(),Formatter().get(),Formatter.leftAlign())
writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign())
writeWithFormat(ppnTv.toByteArray(),Formatter().get(),Formatter.rightAlign())
val ppnValue = ValidNumber().deciformat(salesHeader[0].ppn.toString())
writeWithFormat(ppnValue.toByteArray(),Formatter().get(),Formatter.rightAlign())
writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign())
writeWithFormat(chargeTv.toByteArray(),Formatter().get(),Formatter.rightAlign())
val chargeValue = ValidNumber().deciformat(salesHeader[0].charge.toString())
writeWithFormat(chargeValue.toByteArray(),Formatter().get(),Formatter.rightAlign())
writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign())
writeWithFormat(totalTv.toByteArray(),Formatter().get(),Formatter.rightAlign())
var totalValue = ValidNumber().deciformat(salesHeader[0].allTotal.toString())
writeWithFormat(totalValue.toByteArray(),Formatter().get(),Formatter.rightAlign())
writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign())
writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign())
writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign())
writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign())
writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign())
writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign())
}catch (e: Exception) {
Log.e("PrintActivity", "Exe ", e)
}
}
}
//print code
class Formatter {
/** The format that is being build on */
private val mFormat: ByteArray
init {
// Default:
mFormat = byteArrayOf(27, 33, 0)
}
/**
* Method to get the Build result
*
* #return the format
*/
fun get(): ByteArray {
return mFormat
}
fun bold(): Formatter {
// Apply bold:
mFormat[2] = (0x8 or mFormat[2].toInt()).toByte()
return this
}
fun small(): Formatter {
mFormat[2] = (0x1 or mFormat[2].toInt()).toByte()
return this
}
fun height(): Formatter {
mFormat[2] = (0x10 or mFormat[2].toInt()).toByte()
return this
}
fun width(): Formatter {
mFormat[2] = (0x20 or mFormat[2].toInt()).toByte()
return this
}
fun underlined(): Formatter {
mFormat[2] = (0x80 or mFormat[2].toInt()).toByte()
return this
}
companion object {
fun rightAlign(): ByteArray {
return byteArrayOf(0x1B, 'a'.code.toByte(), 0x02)
}
fun leftAlign(): ByteArray {
return byteArrayOf(0x1B, 'a'.code.toByte(), 0x00)
}
fun centerAlign(): ByteArray {
return byteArrayOf(0x1B, 'a'.code.toByte(), 0x01)
}
}
}//last
fun writeWithFormat(buffer: ByteArray, pFormat: ByteArray?, pAlignment: ByteArray?): Boolean {
val mmOutStream: OutputStream = mBluetoothSocket.outputStream
return try {
// Notify printer it should be printed with given alignment:
mmOutStream.write(pAlignment)
// Notify printer it should be printed in the given format:
mmOutStream.write(pFormat)
// Write the actual data:
mmOutStream.write(buffer, 0, buffer.size)
// Share the sent message back to the UI Activity
//App.getInstance().getHandler().obtainMessage(MESSAGE_WRITE, buffer.size, -1, buffer).sendToTarget()
true
} catch (e: IOException) {
Log.e(TAG, "Exception during write", e)
false
}
}
//print code close
Using Thermal Printer repo references, I managed to print image to Bluetooth thermal printer. Make sure to use a proper black and white image to print.
Here is the piece of code I used to make a java class
--BitmapHelper.java.
public class BitmapHelper {
private static String[] binaryArray = { "0000", "0001", "0010", "0011",
"0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011",
"1100", "1101", "1110", "1111" };
public static byte[] decodeBitmap(Bitmap bmp){
//Bitmap bmp = Bitmap.createScaledBitmap(bitmap, 50, 50, false);
int maxWidth = 350;
int bmpWidth = bmp.getWidth();
int bmpHeight = bmp.getHeight();
if(bmpWidth > maxWidth){
float aspectRatio = bmp.getWidth() /
(float) bmp.getHeight();
bmpWidth = maxWidth;
bmpHeight = Math.round(bmpWidth / aspectRatio);
bmp = Bitmap.createScaledBitmap(bmp, bmpWidth, bmpHeight, false);
}
List<String> list = new ArrayList<>(); //binaryString list
StringBuffer sb;
int zeroCount = bmpWidth % 8;
StringBuilder zeroStr = new StringBuilder();
if (zeroCount > 0) {
for (int i = 0; i < (8 - zeroCount); i++) {
zeroStr.append("0");
}
}
for (int i = 0; i < bmpHeight; i++) {
sb = new StringBuffer();
for (int j = 0; j < bmpWidth; j++) {
int color = bmp.getPixel(j, i);
int r = (color >> 16) & 0xff;
int g = (color >> 8) & 0xff;
int b = color & 0xff;
// if color close to white,bit='0', else bit='1'
if (r > 160 && g > 160 && b > 160)
sb.append("0");
else
sb.append("1");
}
if (zeroCount > 0) {
sb.append(zeroStr);
}
list.add(sb.toString());
}
List<String> bmpHexList = binaryListToHexStringList(list);
String commandHexString = "1D763000";
String widthHexString = Integer
.toHexString(bmpWidth % 8 == 0 ? bmpWidth / 8
: (bmpWidth / 8 + 1));
if (widthHexString.length() > 2) {
Log.e("decodeBitmap error", " width is too large");
return null;
} else if (widthHexString.length() == 1) {
widthHexString = "0" + widthHexString;
}
widthHexString = widthHexString + "00";
String heightHexString = Integer.toHexString(bmpHeight);
if (heightHexString.length() > 2) {
Log.e("decodeBitmap error", " height is too large");
return null;
} else if (heightHexString.length() == 1) {
heightHexString = "0" + heightHexString;
}
heightHexString = heightHexString + "00";
List<String> commandList = new ArrayList<>();
commandList.add(commandHexString+widthHexString+heightHexString);
commandList.addAll(bmpHexList);
return hexList2Byte(commandList);
}
private static List<String> binaryListToHexStringList(List<String> list) {
List<String> hexList = new ArrayList<String>();
for (String binaryStr : list) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < binaryStr.length(); i += 8) {
String str = binaryStr.substring(i, i + 8);
String hexString = myBinaryStrToHexString(str);
sb.append(hexString);
}
hexList.add(sb.toString());
}
return hexList;
}
private static String myBinaryStrToHexString(String binaryStr) {
StringBuilder hex = new StringBuilder();
String f4 = binaryStr.substring(0, 4);
String b4 = binaryStr.substring(4, 8);
String hexStr = "0123456789ABCDEF";
for (int i = 0; i < binaryArray.length; i++) {
if (f4.equals(binaryArray[i]))
hex.append(hexStr.substring(i, i + 1));
}
for (int i = 0; i < binaryArray.length; i++) {
if (b4.equals(binaryArray[i]))
hex.append(hexStr.substring(i, i + 1));
}
return hex.toString();
}
private static byte[] hexList2Byte(List<String> list) {
List<byte[]> commandList = new ArrayList<byte[]>();
for (String hexStr : list) {
commandList.add(hexStringToBytes(hexStr));
}
return sysCopy(commandList);
}
private static byte[] hexStringToBytes(String hexString) {
if (hexString == null || hexString.equals("")) {
return null;
}
hexString = hexString.toUpperCase();
int length = hexString.length() / 2;
char[] hexChars = hexString.toCharArray();
byte[] d = new byte[length];
for (int i = 0; i < length; i++) {
int pos = i * 2;
d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
}
return d;
}
private static byte[] sysCopy(List<byte[]> srcArrays) {
int len = 0;
for (byte[] srcArray : srcArrays) {
len += srcArray.length;
}
byte[] destArray = new byte[len];
int destLen = 0;
for (byte[] srcArray : srcArrays) {
System.arraycopy(srcArray, 0, destArray, destLen, srcArray.length);
destLen += srcArray.length;
}
return destArray;
}
private static byte charToByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}
}
Then I use it in the print activity:
private fun p2(){
val convertBmp : Bitmap
convertBmp = BitmapFactory.decodeResource(getResources(),com.example.ronibluetooth.R.drawable.poly)
val decodeBmp = BitmapHelper.decodeBitmap(convertBmp)
val scope = CoroutineScope(Dispatchers.IO)
scope.launch {
try {
val os =mBluetoothSocket.outputStream
os.write(decodeBmp,0,decodeBmp.size)
}
catch (e: Exception) {
Log.e("PrintActivity", "Exe ", e)
}
}
}
image to print
result print
We used to write code in .Net Framework for DataTable filtering on server side.
This was the old code where HttpContext.Request was working fine. Now in .Net 6 how we can establish the same search and get HttpContext as well in any controller or model class from jquery.
This function is static and I am stuck in HttpContext.Request line where this is throwing exception "Httpcontext does not exist" even if we use IHttpContextAccessor here. How can we access that variable as that is defined in Program.cs.
public static DataTable FilterTable(DataTable dt, ref int Fcount, JQPM p)
{
p.sColumnslist = p.sColumns.Split(',');
string Fstring = ""; Int32 intVal = 0;
if (!string.IsNullOrEmpty(p.sSearch))
{
string[] Arr = p.sSearch.Trim().Split(' ');
for (int i = 0; i < Arr.Length; i++)
{
if (Arr[i] != "")
{
Fstring = "0=1 ";
for (int j = 0; j < p.sColumnslist.Length; j++)
{
if (Convert.ToBoolean(System.Web.HttpContext.Request["bSearchable_" + j]))
{
if (dt.Columns[p.sColumnslist[j]].DataType.Name == "String")
{
Fstring += " or " + p.sColumnslist[j] + " LIKE '%" + Arr[i] + "%'";
}
else if (dt.Columns[p.sColumnslist[j]].DataType.Name == "DateTime")
{
Fstring += " or " + p.sColumnslist[j] + "Format LIKE '%" + Arr[i] + "%'";
}
else
{
if (Int32.TryParse(Arr[i], out intVal))
{
Fstring += " or " + p.sColumnslist[j] + " = " + intVal;
}
}
}
}
//Fstring += " PartyName LIKE '%" + Arr[i] + "%'";
//if (Int32.TryParse(Arr[i], out intVal))
//{
// Fstring += " or SaleVoucherNo = " + intVal;
//}
//Fstring += " or SaleDateFormat LIKE '%" + Arr[i] + "%'";
//dt = GetDatatable(dt, Fstring, ref Fcount, p); Fstring = "";
dt = SearchDatatable(dt, Fstring, ref Fcount, p); Fstring = "";
}
}
}
//else
//{
//dt = GetDatatable(dt, Fstring, ref Fcount, p);
dt = GetDatatable(dt, ref Fcount, p);
//}
return dt;
}
System.Web.HttpContext has changed to Microsoft.AspNetCore.Http.HttpContext; you will need to pass the instance of this from where HttpContext is available into this function.
public static DataTable FilterTable(DataTable dt, ref int Fcount, JQPM p)
becomes
public static DataTable FilterTable(Microsoft.AspNetCore.Http.HttpContext httpContext, DataTable dt, ref int Fcount, JQPM p)
If you are retrieving "bSearchable_" + j from the QueryString and it will only contain that key once you can then use
httpContext.Request.Query["bSearchable_" + j].ToString();
where httpContext is the instance you pass in.
See:
https://learn.microsoft.com/en-us/aspnet/core/migration/http-modules?view=aspnetcore-6.0#migrating-to-the-new-httpcontext
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-context?view=aspnetcore-6.0
I'm newbie in antlr
Because of a migration to java 8 , i must migrate an antlrv3 code from 3.2 to 3.5.2.
I have nothing changed in the antlr grammar who work perfectly with the version 3.2 and java 7 (target java 6)
With the version 3.5.2 of antlr maven generate compilation error like:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.7.0:compile (default-compile) on project ccff-sql2xpath: Compilation failure: Compilation failure:
[ERROR] /C:/ProjectSVN/JSR170/ccff-sql2xpath/target/generated-sources/antlr3/sql2xpath/query/compiler/TParser.java:[262,73] cannot find symbol
[ERROR] symbol: variable props
[ERROR] location: variable p of type org.antlr.runtime.ParserRuleReturnScope
I think that something has changed in the way of antlr v3.5.2 generate the code because i have more than 77600 lines with this one and 'only' 3181 lines with the older version of antlr in the TParser.java generated file
Can you help me ?
Here is the parser grammar:
parser grammar TParser;
options {
language = Java;
output = AST;
superClass = AbstractTParser;
tokenVocab = TLexer;
}
#header {
package sql2xpath.query.compiler;
import sql2xpath.query.xpath.XPathException;
import sql2xpath.query.xpath.constraint.TemporaryPathConstraint;
}
//=============================================================================
query
: s=select (f=from)? (w=where)? (o=orderby)? EOF;
//=============================================================================
select
: SELECT^ p=proplist {
for (String o: ((List<String>) p.props)) {
composer.getColumnSpecifier().addProperty(o);
}
};
//=============================================================================
from returns[String res = "unknown"]
: FROM^ n=ntlist {
if (n.nodetypes.size() > 1)
throw new XPathException("Unable to deal with joined tables in FROM clause");
composer.getPathConstraint().setTypeName(toCompactStringTree(n.nodetypes.get(0)));
};
//=============================================================================
where returns[String res = "unknown"]
: WHERE^ o=orexpression[true] {
if (o.res != null) {
// System.out.println("add constraint: " + o.res);
composer.getPropertyConstraint().addConstraint(o.res);
}
};
//=============================================================================
orderby returns[String res = "unknown"]
: (ORDER BY)^ p=propname d=(DESC | ASC)? {
if (d == null)
composer.getOrderingSpecifier().addProperty(p.res, null);
else if (d.getType() == ASC)
composer.getOrderingSpecifier().addProperty(p.res, "ascending");
else
composer.getOrderingSpecifier().addProperty(p.res, "descending");
} (COMA q=propname e=(DESC | ASC)? {
if (e == null)
composer.getOrderingSpecifier().addProperty(q.res, null);
else if (e.getType() == ASC)
composer.getOrderingSpecifier().addProperty(q.res, "ascending");
else
composer.getOrderingSpecifier().addProperty(q.res, "descending");
})* ;
//=============================================================================
proplist returns[Object props]
#init{
List<String> l = new ArrayList<String>();
}
: a=propname { l.add(a.res); } (COMA b=propname { l.add(b.res); })* { $props = l; };
//=============================================================================
ntlist returns[List nodetypes]
: c+=complexpropname (COMA c+=complexpropname)* { $nodetypes = $c; };
//=============================================================================
orexpression[boolean b] returns[String res = null]
#init{
List<String> l = new ArrayList<String>();
List<Object> p = new ArrayList<Object>();
}
: a=andexpression[b] {
p.addAll(((List<Object>)(((Object []) a.res)[1])));
l.add((String)(((Object []) a.res)[0]));
} (OR^ c=andexpression[b] {
p.addAll(((List<Object>)(((Object []) c.res)[1])));
l.add((String)(((Object []) c.res)[0]));
})* {
StringBuffer sb = new StringBuffer();
for (String s: l)
if (s!=null)
sb.append(s + " or ");
if (sb.length() > 0)
$res = sb.substring(0,sb.length()-4);
if (p.size() > 2)
throw new XPathException("Unable to deal with more than two path constraints");
else if (p.size() == 2) {
if (!$b)
throw new XPathException("Cannot deal with negated or clauses");
TemporaryPathConstraint pc1 = (TemporaryPathConstraint) p.get(0);
TemporaryPathConstraint pc2 = (TemporaryPathConstraint) p.get(1);
//LOGGER.debug("Found or-ed constraints on jcr:path = " + pc1.path + " OR " + pc2.path);
if (pc1.b && pc2.b) {
composer.getPathConstraint().orConstraint(pc1.path, pc2.path);
} else
throw new XPathException("Only positive path constraints can be in the same or clause");
}else if (p.size() == 1) {
if (!$b)
throw new XPathException("Cannot deal with single negated path constraint");
TemporaryPathConstraint pc1 = (TemporaryPathConstraint) p.get(0);
//LOGGER.debug("Found single constraint on jcr:path = " + pc1.path);
if (pc1.b) {
composer.getPathConstraint().singleConstraint(pc1.path);
} else {
throw new XPathException("Cannot deal with negative single path constraints");
}
}
};
//=============================================================================
andexpression[boolean b] returns[Object res = null]
#init{
List<String> l = new ArrayList<String>();
List<Object> p = new ArrayList<Object>();
String k = null;
}
: a=notexpression[b] { if (a.res instanceof TemporaryPathConstraint) p.add(a.res); else l.add((String)a.res); } (AND^ c=notexpression[b] { if (c.res instanceof TemporaryPathConstr
StringBuffer sb = new StringBuffer();
for (String s: l)
if (s!=null)
sb.append(s + " and ");
if (sb.length() > 0)
k = sb.substring(0,sb.length()-5);
if (p.size() > 2)
throw new XPathException("Unable to deal with more than two path constraints");
else if (p.size() == 2) {
if (!$b)
throw new XPathException("Cannot deal with negated and clauses");
TemporaryPathConstraint pc1 = (TemporaryPathConstraint) p.get(0);
TemporaryPathConstraint pc2 = (TemporaryPathConstraint) p.get(1);
//LOGGER.debug("Found and-ed constraints on jcr:path = " + pc1.path + " AND " + pc2.path);
if (pc1.b && !pc2.b) {
composer.getPathConstraint().andNotConstraint(pc1.path, pc2.path);
} else if (pc2.b && !pc1.b) {
composer.getPathConstraint().andNotConstraint(pc2.path, pc1.path);
} else
throw new XPathException("Only one positive and one negative path constraint can be in the same and clause");
p.clear();
}
$res = new Object [] {k, p};
};
//=============================================================================
notexpression[boolean b] returns[Object res = null]
: NOT^ d=containsexpression[false] { if (!$b) throw new XPathException("Impossible to parse nested NOT operators"); $res = d.res;}
| c=containsexpression[b] {$res = c.res; };
//=============================================================================
containsexpression[boolean b] returns[Object res = null]
: c=containsfun[b] { $res = c.res; }
| v=value IN p=propname { $res = composer.getPropertyConstraint().getComparingConstraint(p.res, "=", v.res, b); }
| o=operatorexpression[b] { $res = o.res; };
//=============================================================================
operatorexpression[boolean b] returns[Object res = null]
: p=propname o=op v=value {
if ("jcr:path".equals(p.res))
if (!"=".equals(o.res))
throw new XPathException("Impossible to use other operator than \"=\" or \"LIKE\" with jcr:xpath property");
else {
TemporaryPathConstraint tpc = new TemporaryPathConstraint(TemporaryPathConstraint.EQUAL);
tpc.path = v.res;
tpc.b = $b;
$res = tpc;
}
//composer.getPathConstraint().addConstraintAndProcess(v.res, b, false);
else
$res = composer.getPropertyConstraint().getComparingConstraint(p.res, o.res, v.res, b);
}
| p=propname IS NULL { $res = composer.getPropertyConstraint().getIsNullConstraint(p.res, b); }
| p=propname IS NOT NULL { $res = composer.getPropertyConstraint().getIsNotNullConstraint(p.res, b); }
| l=like[b] { $res = l.res; }
| t=parentexpression[b] { $res = t.res; };
//=============================================================================
op returns[String res = "unknown"]
: EQ { $res = "="; }
| NEQ { $res = "!="; }
| LEQ { $res = "<="; }
| LES { $res = "<"; }
| GEQ { $res = ">="; }
| GRE { $res = ">"; };
//=============================================================================
parentexpression[boolean b] returns[String res = "unknown"]
: LEFT_PAREN o=orexpression[b] RIGHT_PAREN { $res = "(" + o.res + ")"; };
//=============================================================================
propname returns[String res = "unknown"]
: QUOT c=complexpropname QUOT { $res = $c.res; }
| c=complexpropname { $res = $c.res; };
//=============================================================================
complexpropname returns[String res = "unknown"]
: a=simplepropname (DOT b=simplepropname)? {$res = a.res; if (b != null) $res += "." + b.res;};
//=============================================================================
simplepropname returns[String res = "unknown"]
: a=identifier (COLON b=identifier)? {$res = a.res; if (b != null) $res += ":" + b.res;};
//=============================================================================
identifier returns[String res = "unknown"]
: nq=NonQuotedIdentifier { $res = $nq.getText(); }
| q=QuotedIdentifier { $res = q.getText(); }
| l=Letter { $res = l.getText(); }
| STAR { $res = "*"; };
//=============================================================================
value returns[String res = "value"]
: x=complexpropname { $res = x.res; }
| c=constant { $res = c.res; };
//=============================================================================
like[boolean b] returns[Object res = null]
: p=propname LIKE e=expression (c = escape)? {
if ("jcr:path".equals(p.res)) {
TemporaryPathConstraint tpc = new TemporaryPathConstraint(TemporaryPathConstraint.LIKE);
tpc.path = e.res;
tpc.b = $b;
$res = tpc;
// composer.getPathConstraint().addConstraintAndProcess(((c == null) ? e.res : e.res.replaceAll(c.res, "\\" + c.res)), $b, false);
} else
$res = composer.getPropertyConstraint().getLikeConstraint(p.res, ((c == null) ? e.res : e.res.replaceAll(c.res, "\\" + c.res)), $b);
};
//=============================================================================
escape returns[String res = "escape"]
: ESCAPE e=expression { $res = e.res; };
//=============================================================================
expression returns[String res = "expression"]
: (u=unaryOperator)? c=constant { $res = ((u!=null)?u.res:"") + c.res; };
//=============================================================================
unaryOperator returns[String res = "unaryOperator"]
: MINUS { $res = "-"; };
//=============================================================================
constant returns[String res = "constant"]
: Number { $res = $Number.getText(); }
| NULL { $res = $NULL.getText(); }
| s=stringLiteral { $res = s.res; }
| Currency { $res = $Currency.getText(); }
| ODBCDateTime { $res = $ODBCDateTime.getText(); };
//=============================================================================
stringLiteral returns[String res = "stringLiteral"]
: UnicodeStringLiteral { $res = $UnicodeStringLiteral.getText(); }
| ASCIIStringLiteral { $res = $ASCIIStringLiteral.getText(); };
//=============================================================================
containsfun[boolean b] returns[String res = "containsfun"]
: CONTAINS_FUN c=containscope COMA e=expression RIGHT_PAREN {
$res = composer.getPropertyConstraint().getContainsConstraint(c.res, e.res, b);
};
//=============================================================================
containscope returns[String res = "containscope"]
: c=complexpropname { $res = c.res; }
| DOT { $res = "."; };
Here is the code of the method where is the error:
// $ANTLR start "select"
// be\\fgov\\minfin\\ccff\\jcr2\\sql2xpath\\query\\compiler\\TParser.g:27:4: select : SELECT ^p= proplist ;
public final TParser.select_return select() throws RecognitionException {
TParser.select_return retval = new TParser.select_return();
retval.start = input.LT(1);
Object root_0 = null;
Token SELECT2=null;
ParserRuleReturnScope p =null;
Object SELECT2_tree=null;
try {
// sql2xpath\\query\\compiler\\TParser.g:28:5: ( SELECT ^p= proplist )
// sql2xpath\\query\\compiler\\TParser.g:28:7: SELECT ^p= proplist
{
root_0 = (Object)adaptor.nil();
SELECT2=(Token)match(input,SELECT,FOLLOW_SELECT_in_select186);
SELECT2_tree = (Object)adaptor.create(SELECT2);
root_0 = (Object)adaptor.becomeRoot(SELECT2_tree, root_0);
pushFollow(FOLLOW_proplist_in_select191);
p=proplist();
state._fsp--;
adaptor.addChild(root_0, p.getTree());
for (String o: ((List<String>) p.props)) { // <=====[ERROR]
composer.getColumnSpecifier().addProperty(o);
}
}
retval.stop = input.LT(-1);
retval.tree = (Object)adaptor.rulePostProcessing(root_0);
adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
}
catch (RecognitionException re) {
reportError(re);
recover(input,re);
retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re);
}
finally {
// do for sure before leaving
}
return retval;
}
// $ANTLR end "select"
I think I understood the compilation error:
The p property of type ParserRuleReturnScope is initialized with a method that returns a class of type proplist_return and extends the class ParserRuleReturnScope.
ParserRuleReturnScope p =null;
...
p=proplist(); // (proplist_return extend ParserRuleReturnScope)
...
for (String o: ((List<String>) p.props)) { // <=====[COMPILATION ERROR]
Because the class prolist_return is a child of ParserRuleReturnScope, p must be cast before searching for properties included in the child class, here the props property
like this:
proplist_return castP = (proplist_return) p;
for (String o: ((List<String>) castP.props)) {
With version 3.2, the plugin generates an error free code. with version 3.5.2, it generates these errors!
I understand the cause of the compilation error.
In fact version 3.5.2 of ANTLR is stricter, and in the action part of my rule 'select' in the grammar antlr, I forgot to reference the variable p and add a $ before. That's why the generator does not cast my class (see comment above)
the wrong grammar is:
select
: SELECT^ p=proplist {
for (String o: ((List<String>) p.props)) {
composer.getColumnSpecifier().addProperty(o);
}
};
So the solution is:
select
: SELECT^ p=proplist {
for (String o: ((List<String>) $p.props)) {
composer.getColumnSpecifier().addProperty(o);
}
};
For example, the parsing tree from Stanford Sentiment Treebank
"(2 (2 (2 near) (2 (2 the) (2 end))) (3 (3 (2 takes) (2 (2 on) (2 (2 a) (2 (2 whole) (2 (2 other) (2 meaning)))))) (2 .)))",
where the number is the sentiment label of each node.
I want to add POS tagging information to each node. Such as:
"(NP (ADJP (IN near)) (DT the) (NN end)) "
I have tried to directly parse the sentence, but the resulted tree is different from that in the Sentiment Treebank (may be because of the parsing version or parameters, I have tried to contact to the author but there is no response).
How can I obtain the tagging information?
I think the code in edu.stanford.nlp.sentiment.BuildBinarizedDataset should be helpful. The main() method steps through how these binary trees can be created in Java code.
Some key lines to look out for in the code:
LexicalizedParser parser = LexicalizedParser.loadModel(parserModel);
TreeBinarizer binarizer = TreeBinarizer.simpleTreeBinarizer(parser.getTLPParams().headFinder(), parser.treebankLanguagePack());
...
Tree tree = parser.apply(tokens);
Tree binarized = binarizer.transformTree(tree);
You can access the node tag information from the Tree object. You should look at the javadoc for edu.stanford.nlp.trees.Tree to see how to access this information.
Also in this answer I have some code that shows accessing a Tree:
How to get NN andNNS from a text?
You want to look at the label() of each tree and subtree to get the tag for a node.
Here is the reference on GitHub to BuildBinarizedDataset.java:
https://github.com/stanfordnlp/CoreNLP/blob/master/src/edu/stanford/nlp/sentiment/BuildBinarizedDataset.java
Please let me know if anything is unclear about this and I can provide further assistance!
First, you need to download the Stanford Parser
Set up
private LexicalizedParser parser;
private TreeBinarizer binarizer;
private CollapseUnaryTransformer transformer;
parser = LexicalizedParser.loadModel(PCFG_PATH);
binarizer = TreeBinarizer.simpleTreeBinarizer(
parser.getTLPParams().headFinder(), parser.treebankLanguagePack());
transformer = new CollapseUnaryTransformer();
Parse
Tree tree = parser.apply(tokens);
Access POSTAG
public String[] constTreePOSTAG(Tree tree) {
Tree binarized = binarizer.transformTree(tree);
Tree collapsedUnary = transformer.transformTree(binarized);
Trees.convertToCoreLabels(collapsedUnary);
collapsedUnary.indexSpans();
List<Tree> leaves = collapsedUnary.getLeaves();
int size = collapsedUnary.size() - leaves.size();
String[] tags = new String[size];
HashMap<Integer, Integer> index = new HashMap<Integer, Integer>();
int idx = leaves.size();
int leafIdx = 0;
for (Tree leaf : leaves) {
Tree cur = leaf.parent(collapsedUnary); // go to preterminal
int curIdx = leafIdx++;
boolean done = false;
while (!done) {
Tree parent = cur.parent(collapsedUnary);
if (parent == null) {
tags[curIdx] = cur.label().toString();
break;
}
int parentIdx;
int parentNumber = parent.nodeNumber(collapsedUnary);
if (!index.containsKey(parentNumber)) {
parentIdx = idx++;
index.put(parentNumber, parentIdx);
} else {
parentIdx = index.get(parentNumber);
done = true;
}
tags[curIdx] = parent.label().toString();
cur = parent;
curIdx = parentIdx;
}
}
return tags;
}
Here is the full source code ConstituencyParse.java that run:
Use param:
java ConstituencyParse -tokpath outputtoken.toks -parentpath outputparent.txt -tagpath outputag.txt < input_sentence_in_text_file_one_sent_per_line.txt
(Note: the source code is adapt from treelstm repo, you also need to replace preprocess-sst.py to call ConstituencyParse.java file below)
import edu.stanford.nlp.process.WordTokenFactory;
import edu.stanford.nlp.ling.HasWord;
import edu.stanford.nlp.ling.Word;
import edu.stanford.nlp.ling.CoreLabel;
import edu.stanford.nlp.ling.TaggedWord;
import edu.stanford.nlp.process.PTBTokenizer;
import edu.stanford.nlp.util.StringUtils;
import edu.stanford.nlp.parser.lexparser.LexicalizedParser;
import edu.stanford.nlp.parser.lexparser.TreeBinarizer;
import edu.stanford.nlp.tagger.maxent.MaxentTagger;
import edu.stanford.nlp.trees.GrammaticalStructure;
import edu.stanford.nlp.trees.GrammaticalStructureFactory;
import edu.stanford.nlp.trees.PennTreebankLanguagePack;
import edu.stanford.nlp.trees.Tree;
import edu.stanford.nlp.trees.Trees;
import edu.stanford.nlp.trees.TreebankLanguagePack;
import edu.stanford.nlp.trees.TypedDependency;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.StringReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.HashMap;
import java.util.Properties;
import java.util.Scanner;
public class ConstituencyParse {
private boolean tokenize;
private BufferedWriter tokWriter, parentWriter, tagWriter;
private LexicalizedParser parser;
private TreeBinarizer binarizer;
private CollapseUnaryTransformer transformer;
private GrammaticalStructureFactory gsf;
private static final String PCFG_PATH = "edu/stanford/nlp/models/lexparser/englishPCFG.ser.gz";
public ConstituencyParse(String tokPath, String parentPath, String tagPath, boolean tokenize) throws IOException {
this.tokenize = tokenize;
if (tokPath != null) {
tokWriter = new BufferedWriter(new FileWriter(tokPath));
}
parentWriter = new BufferedWriter(new FileWriter(parentPath));
tagWriter = new BufferedWriter(new FileWriter(tagPath));
parser = LexicalizedParser.loadModel(PCFG_PATH);
binarizer = TreeBinarizer.simpleTreeBinarizer(
parser.getTLPParams().headFinder(), parser.treebankLanguagePack());
transformer = new CollapseUnaryTransformer();
// set up to produce dependency representations from constituency trees
TreebankLanguagePack tlp = new PennTreebankLanguagePack();
gsf = tlp.grammaticalStructureFactory();
}
public List<HasWord> sentenceToTokens(String line) {
List<HasWord> tokens = new ArrayList<>();
if (tokenize) {
PTBTokenizer<Word> tokenizer = new PTBTokenizer(new StringReader(line), new WordTokenFactory(), "");
for (Word label; tokenizer.hasNext(); ) {
tokens.add(tokenizer.next());
}
} else {
for (String word : line.split(" ")) {
tokens.add(new Word(word));
}
}
return tokens;
}
public Tree parse(List<HasWord> tokens) {
Tree tree = parser.apply(tokens);
return tree;
}
public String[] constTreePOSTAG(Tree tree) {
Tree binarized = binarizer.transformTree(tree);
Tree collapsedUnary = transformer.transformTree(binarized);
Trees.convertToCoreLabels(collapsedUnary);
collapsedUnary.indexSpans();
List<Tree> leaves = collapsedUnary.getLeaves();
int size = collapsedUnary.size() - leaves.size();
String[] tags = new String[size];
HashMap<Integer, Integer> index = new HashMap<Integer, Integer>();
int idx = leaves.size();
int leafIdx = 0;
for (Tree leaf : leaves) {
Tree cur = leaf.parent(collapsedUnary); // go to preterminal
int curIdx = leafIdx++;
boolean done = false;
while (!done) {
Tree parent = cur.parent(collapsedUnary);
if (parent == null) {
tags[curIdx] = cur.label().toString();
break;
}
int parentIdx;
int parentNumber = parent.nodeNumber(collapsedUnary);
if (!index.containsKey(parentNumber)) {
parentIdx = idx++;
index.put(parentNumber, parentIdx);
} else {
parentIdx = index.get(parentNumber);
done = true;
}
tags[curIdx] = parent.label().toString();
cur = parent;
curIdx = parentIdx;
}
}
return tags;
}
public int[] constTreeParents(Tree tree) {
Tree binarized = binarizer.transformTree(tree);
Tree collapsedUnary = transformer.transformTree(binarized);
Trees.convertToCoreLabels(collapsedUnary);
collapsedUnary.indexSpans();
List<Tree> leaves = collapsedUnary.getLeaves();
int size = collapsedUnary.size() - leaves.size();
int[] parents = new int[size];
HashMap<Integer, Integer> index = new HashMap<Integer, Integer>();
int idx = leaves.size();
int leafIdx = 0;
for (Tree leaf : leaves) {
Tree cur = leaf.parent(collapsedUnary); // go to preterminal
int curIdx = leafIdx++;
boolean done = false;
while (!done) {
Tree parent = cur.parent(collapsedUnary);
if (parent == null) {
parents[curIdx] = 0;
break;
}
int parentIdx;
int parentNumber = parent.nodeNumber(collapsedUnary);
if (!index.containsKey(parentNumber)) {
parentIdx = idx++;
index.put(parentNumber, parentIdx);
} else {
parentIdx = index.get(parentNumber);
done = true;
}
parents[curIdx] = parentIdx + 1;
cur = parent;
curIdx = parentIdx;
}
}
return parents;
}
// convert constituency parse to a dependency representation and return the
// parent pointer representation of the tree
public int[] depTreeParents(Tree tree, List<HasWord> tokens) {
GrammaticalStructure gs = gsf.newGrammaticalStructure(tree);
Collection<TypedDependency> tdl = gs.typedDependencies();
int len = tokens.size();
int[] parents = new int[len];
for (int i = 0; i < len; i++) {
// if a node has a parent of -1 at the end of parsing, then the node
// has no parent.
parents[i] = -1;
}
for (TypedDependency td : tdl) {
// let root have index 0
int child = td.dep().index();
int parent = td.gov().index();
parents[child - 1] = parent;
}
return parents;
}
public void printTokens(List<HasWord> tokens) throws IOException {
int len = tokens.size();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < len - 1; i++) {
if (tokenize) {
sb.append(PTBTokenizer.ptbToken2Text(tokens.get(i).word()));
} else {
sb.append(tokens.get(i).word());
}
sb.append(' ');
}
if (tokenize) {
sb.append(PTBTokenizer.ptbToken2Text(tokens.get(len - 1).word()));
} else {
sb.append(tokens.get(len - 1).word());
}
sb.append('\n');
tokWriter.write(sb.toString());
}
public void printParents(int[] parents) throws IOException {
StringBuilder sb = new StringBuilder();
int size = parents.length;
for (int i = 0; i < size - 1; i++) {
sb.append(parents[i]);
sb.append(' ');
}
sb.append(parents[size - 1]);
sb.append('\n');
parentWriter.write(sb.toString());
}
public void printTags(String[] tags) throws IOException {
StringBuilder sb = new StringBuilder();
int size = tags.length;
for (int i = 0; i < size - 1; i++) {
sb.append(tags[i]);
sb.append(' ');
}
sb.append(tags[size - 1]);
sb.append('\n');
tagWriter.write(sb.toString().toLowerCase());
}
public void close() throws IOException {
if (tokWriter != null) tokWriter.close();
parentWriter.close();
tagWriter.close();
}
public static void main(String[] args) throws Exception {
String TAGGER_MODEL = "stanford-tagger/models/english-left3words-distsim.tagger";
Properties props = StringUtils.argsToProperties(args);
if (!props.containsKey("parentpath")) {
System.err.println(
"usage: java ConstituencyParse -deps - -tokenize - -tokpath <tokpath> -parentpath <parentpath>");
System.exit(1);
}
// whether to tokenize input sentences
boolean tokenize = false;
if (props.containsKey("tokenize")) {
tokenize = true;
}
// whether to produce dependency trees from the constituency parse
boolean deps = false;
if (props.containsKey("deps")) {
deps = true;
}
String tokPath = props.containsKey("tokpath") ? props.getProperty("tokpath") : null;
String parentPath = props.getProperty("parentpath");
String tagPath = props.getProperty("tagpath");
ConstituencyParse processor = new ConstituencyParse(tokPath, parentPath, tagPath, tokenize);
Scanner stdin = new Scanner(System.in);
int count = 0;
long start = System.currentTimeMillis();
while (stdin.hasNextLine() && count < 2) {
String line = stdin.nextLine();
List<HasWord> tokens = processor.sentenceToTokens(line);
//end tagger
Tree parse = processor.parse(tokens);
// produce parent pointer representation
int[] parents = deps ? processor.depTreeParents(parse, tokens)
: processor.constTreeParents(parse);
String[] tags = processor.constTreePOSTAG(parse);
// print
if (tokPath != null) {
processor.printTokens(tokens);
}
processor.printParents(parents);
processor.printTags(tags);
// print tag
StringBuilder sb = new StringBuilder();
int size = tags.length;
for (int i = 0; i < size - 1; i++) {
sb.append(tags[i]);
sb.append(' ');
}
sb.append(tags[size - 1]);
sb.append('\n');
count++;
if (count % 100 == 0) {
double elapsed = (System.currentTimeMillis() - start) / 1000.0;
System.err.printf("Parsed %d lines (%.2fs)\n", count, elapsed);
}
}
long totalTimeMillis = System.currentTimeMillis() - start;
System.err.printf("Done: %d lines in %.2fs (%.1fms per line)\n",
count, totalTimeMillis / 100.0, totalTimeMillis / (double) count);
processor.close();
}
}
I wrote a small function that splits a number to commas but I have to run over the number too many times. Can you sugest me a better way to do this?
public static function getCommaString(value:Number):String {
var stringValue:String = value.toString();
if (stringValue.length <= 3) {
return stringValue;
}
var i:int = stringValue.length % 3;
if (i == 0) {
i = 3;
}
for (; i < stringValue.length; i += 4 ) {
var part1:String = stringValue.substr(0, i);
var part2:String = stringValue.substr(i, stringValue.length);
stringValue = part1.concat(",", part2);
}
return stringValue;
}
I put together a testing class that compares your solution and others, including a solution from this blog post and solutions from this related StackExchange question and formatted them in a consistent way for easy comparison:
package
{
public class CommaNumberSolutions
{
public static function commaify( input:Number ):String
{
var split:Array = input.toString().split( '.' ),
front:String = split[0],
back:String = ( split.length > 1 ) ? "." + split[1] : null,
n:int = input < 0 ? 2 : 1,
commas:int = Math.floor( (front.length - n) / 3 ),
i:int = 1;
for ( ; i <= commas; i++ )
{
n = front.length - (3 * i + i - 1);
front = front.slice( 0, n ) + "," + front.slice( n );
}
if ( back )
return front + back;
else
return front;
}
public static function getCommaString( input:Number ):String
{
var s:String = input.toString();
if ( s.length <= 3 )
return s;
var i:int = s.length % 3;
if ( i == 0 )
i = 3;
for ( ; i < s.length; i += 4 )
{
var part1:String = s.substr(0, i);
var part2:String = s.substr(i, s.length);
s = part1.concat(",", part2);
}
return s;
}
public static function formatNumber( input:Number ):String
{
var s:String = input.toString()
var result:String = ''
while ( s.length > 3 )
{
var chunk:String = s.substr(-3)
s = s.substr(0, s.length - 3)
result = ',' + chunk + result
}
if ( s.length > 0 )
result = s + result
return result
}
public static function commaCoder( input:Number ):String
{
var s:String = "";
var len:Number = input.toString().length;
for ( var i:int = 0; i < len; i++ )
{
if ( (len-i) % 3 == 0 && i != 0)
s += ",";
s += input.toString().charAt(i);
}
return s;
}
public static function regex1( input:Number ):String
{
return input.toString().replace( /-{0,1}(\d)(?=(\d\d\d)+$)/g, "$1," );
}
public static function regex2( input:Number ):String
{
return input.toString().replace( /-{0,1}\d{1,3}(?=(\d{3})+(?!\d))/g , "$&,")
}
public static function addCommas( input:Number ):String
{
var negative:String = "";
if ( input < 0 )
{
negative = "-";
input = Math.abs(input);
}
var s:String = input.toString();
var results:Array = s.split(/\./);
s = results[0];
if ( s.length > 3 )
{
var mod:Number = s.length % 3;
var output:String = s.substr(0, mod);
for ( var i:Number = mod; i < s.length; i += 3 )
{
output += ((mod == 0 && i == 0) ? "" : ",") + s.substr(i, 3);
}
if ( results.length > 1 )
{
if ( results[1].length == 1 )
return negative + output + "." + results[1] + "0";
else
return negative + output + "." + results[1];
}
else
return negative + output;
}
if ( results.length > 1 )
{
if ( results[1].length == 1 )
return negative + s + "." + results[1] + "0";
else
return negative + s + "." + results[1];
}
else
return negative + s;
}
}
}
You can see a more detailed analysis at my other answer but you can compare the compactness of each solution and weigh that against their accuracy and performance, however for the sake of brevity this solution is the most accurate and performant (though not the most compact):
public function commaify( input:Number ):String
{
var split:Array = input.toString().split( '.' ),
front:String = split[0],
back:String = ( split.length > 1 ) ? "." + split[1] : null,
n:int = input < 0 ? 2 : 1,
commas:int = Math.floor( (front.length - n) / 3 ),
i:int = 1;
for ( ; i <= commas; i++ )
{
n = front.length - (3 * i + i - 1);
front = front.slice( 0, n ) + "," + front.slice( n );
}
if ( back )
return front + back;
else
return front;
}