Node.JS string array sort is not working - node.js

Hi I am absolute beginner of node.js Today I tried the following code
var fs, arr;
var dir, str;
var cont, item;
fs=require('fs');
cont=fs.readFileSync('unsort.txt').toString();
arr=cont.split('\n');
arr.sort();
for(str=arr.shift();str&&(item=arr.shift());)
str+='\n'+item;
fs.writeFileSync('sort_by_script.txt', str);
the above node.js code reads a file as string, from the directory of the node.exe. Splits the string by newline ('\n') to get a array. Sorts the array and prints the sorted array to the file. So as a whole the script reads a file sort the entries and saves the sorted entry in another file. The problem is the sorted order is not correct. I tried sorting the content of unsort.txt manually using MS Excel by which I got the correct order of sort. Can any one help me why the arr.sort() is not working correct. You can download unsort.txt, sort_by_script.txt, sort_by_ms_excel.txt and node.exe in the package [Sort.rar][1]
Note : unsort.txt has no numbers. All are only alphabets.
Examples from unsort.txt:
appjs
gbi
node
frame
require
process
module
WebSocket
webkitAudioContext
webkitRTCPeerConnection
webkitPeerConnection00
webkitMediaStream
MediaController
HTMLSourceElement
TimeRanges

If you do not pass a custom search function the sort function sorts lexically, numbers get cast to strings and so it happens that e.g. "10" is before "3". So the strings get sorted.
You can pass a custom function to the sort function which decides the order of the items, in case of numbers this would be an example (Be careful as numbers in your example would be strings if you dont cast / parse them to numbers) :
var numsort = function (a, b) {
return a - b;
}
var numbers = new Array(20, 2, 11, 4, 1);
var result = numbers.sort(numsort);
Another example for strings:
var sortstring = function (a, b) {
a = a.toLowerCase();
b = b.toLowerCase();
if (a < b) return 1;
if (a > b) return -1;
return 0;
}

I would use
arr.sort((obj1, obj2) => {
return obj1.localeCompare(obj2);
});
That will most likely solve your issue.

Related

Insert commas into string number

I have this code, and I want to put commas.
I've seen many examples, but I dont now were put the code.
This is my AS3 code:
calccn.addEventListener(MouseEvent.CLICK,result1);
function result1(e:MouseEvent)
{
var vev: Number = (Number(vev.text));
var cn1: Number = (Number(3/100));
var result1f: Number = (Number(vev*cn1));
var round;
round=result1f.toFixed(0);
v3.text = String(round);
}
Example
If the result give me 1528000,32
I want that the result is 1.528.000 or 1 528 000
I didn't know (live and learn, eh), but there's actually a dedicated class: NumberFormatter.
If you want to do the thing on a regular basis, you might want a method to call:
// Implementation.
import flash.globalization.NumberFormatter;
// The default separator is comma.
function formattedNumber(value:Number, separator:String = ","):String
{
var NF:NumberFormatter;
NF = new NumberFormatter("en_US");
// Enforce the use of the given separator.
NF.groupingSeparator = separator;
// Ignore the fraction part.
NF.fractionalDigits = 0;
return NF.formatNumber(value);
}
// Usage.
//Format the given number with spaces for separator.
trace(formattedNumber(1528000.32, " ")); // 1 528 000
//Format the given number with the default separator.
trace(formattedNumber(1528000.32)); // 1,528,000
But if you want just a simple one-timer, and don't really care if it is commas or spaces as long as they present you may just condense in into a single expression:
calccn.addEventListener(MouseEvent.CLICK, result1);
function result1(e:MouseEvent):void
{
// Declaring variables with the same names as
// other entities is a generally bad idea.
var input:Number = Number(vev.text);
var cn1:Number = 3.0 / 100.0;
// Keep in mind that I used int() here as
// a simple tool to remove the fraction part.
v3.text = (new NumberFormatter("en_US")).formatNumber(int(input * cn1));
}

how to use node js buffer with a conversion map

I am following a tutorial about nodejs. In the tutorial it has this example:
const fs = require('fs');
const conversionMap = {
'88': '65',
'89': '66',
'90': '67',
};
fs.readFile(__filename, (err, buffer) => {
let tag = buffer.slice(-4, -1);
for(let i=0;i < tag.length; i++) {
tag[i] = conversionMap[tag[i]];
}
console.log(buffer.toString());
});
// TAG: XYZ
I am pretty sure I know what this example is doing. It is reading the file, then allocating it to a buffer and writing it out. I know that it finds the TAG via slice(-4, -1) (The tag it 1 up from the bottom and for over). I am just not sure it changes it.
Thanks in advance for the help!
Yes it changes each time because it is running a loop and iterating the value of i.
tag will give you the buffer.sliced value and tag.length will have that number.
So the i value will have an initialization with 0 and then it will run the loop till it reaches the tag.length
So if buffer.slice(-4, -1) results in "text", then the loop will consider tag.length as 4 and the i will consider upto 3 (i < tag.length).
So, conversionMap is a map which does the Key= value mapping.
In this case , 88 is the key and the corresponding value is 65 for it.
But , it is doing the conversion for the character's decimal value(which is i ).
You can check that in the ASCII table for your reference.

Add comma sequentially to string in C#

I have a string.
string str = "TTFTTFFTTTTF";
How can I break this string and add character ","?
result should be- TTF,TTF,FTT,TTF
You could use String.Join after you've grouped by 3-chars:
var groups = str.Select((c, ix) => new { Char = c, Index = ix })
.GroupBy(x => x.Index / 3)
.Select(g => String.Concat(g.Select(x => x.Char)));
string result = string.Join(",", groups);
Since you're new to programming. That's a LINQ query so you need to add using System.Linq to the top of your code file.
The Select extension method creates an anonymous type containing the char and the index of each char.
GroupBy groups them by the result of index / 3 which is an integer division that truncates decimal places. That's why you create groups of three.
String.Concat creates a string from the 3 characters.
String.Join concatenates them and inserts a comma delimiter between each.
Here is a really simple solution using StringBuilder
var stringBuilder = new StringBuilder();
for (int i = 0; i < str.Length; i += 3)
{
stringBuilder.AppendFormat("{0},", str.Substring(i, 3));
}
stringBuilder.Length -= 1;
str = stringBuilder.ToString();
I'm not sure if the following is better.
stringBuilder.Append(str.Substring(i, 3)).Append(',');
I would suggest to avoid LINQ in this case as it will perform a lot more operations and this is a fairly simple task.
You can use insert
Insert places one string into another. This forms a new string in your C# program. We use the string Insert method to place one string in the middle of another one—or at any other position.
Tip 1:
We can insert one string at any index into another. IndexOf can return a suitable index.
Tip 2:
Insert can be used to concatenate strings. But this is less efficient—concat, as with + is faster.
for(int i=3;i<=str.Length - 1;i+=4)
{
str=str.Insert(i,",");
}

dart efficient string processing techniques?

I strings in the format of name:key:dataLength:data and these strings can often be chained together. for example "aNum:n:4:9879aBool:b:1:taString:s:2:Hi" this would map to an object something like:
{
aNum: 9879,
aBool: true,
aString: "Hi"
}
I have a method for parsing a string in this format but I'm not sure whether it's use of substring is the most efficient way of pprocessing the string, is there a more efficient way of processing strings in this fashion (repeatedly chopping off the front section):
Map<string, dynamic> fromString(String s){
Map<String, dynamic> _internal = new Map();
int start = 0;
while(start < s.length){
int end;
List<String> parts = new List<String>(); //0 is name, 1 is key, 2 is data length, 3 is data
for(var i = 0; i < 4; i++){
end = i < 3 ? s.indexOf(':') : num.parse(parts[2]);
parts[i] = s.substring(start, end);
start = i < 3 ? end + 1 : end;
}
var tranType = _tranTypesByKey[parts[1]]; //this is just a map to an object which has a function that can convert the data section of the string into an object
_internal[parts[0]] = tranType._fromStr(parts[3]);
}
return _internal;
}
I would try s.split(':') and process the resulting list.
If you do a lot of such operations you should consider creating benchmarks tests, try different techniques and compare them.
If you would still need this line
s = i < 3 ? s.substring(idx + 1) : s.substring(idx);
I would avoid creating a new substring in each iteration but instead just keep track of the next position.
You have to decide how important performance is relative to readability and maintainability of the code.
That said, you should not be cutting off the head of the string repeatedly. That is guaranteed to be inefficient - it'll take time that is quadratic in the number of records in your string, just creating those tail strings.
For parsing each field, you can avoid doing substrings on the length and type fields. For the length field, you can build the number yourself:
int index = ...;
// index points to first digit of length.
int length = 0;
int charCode = source.codeUnitAt(index++);
while (charCode != CHAR_COLON) {
length = 10 * length + charCode - 0x30;
charCode = source.codeUnitAt(index++);
}
// index points to the first character of content.
Since lengths are usually small integers (less than 2<<31), this is likely to be more efficient than creating a substring and calling int.parse.
The type field is a single ASCII character, so you could use codeUnitAt to get its ASCII value instead of creating a single-character string (and then your content interpretation lookup will need to switch on character code instead of character string).
For parsing content, you could pass the source string, start index and length instead of creating a substring. Then the boolean parser can also just read the code unit instead of the singleton character string, the string parser can just make the substring, and the number parser will likely have to make a substring too and call double.parse.
It would be convenient if Dart had a double.parseSubstring(source, [int from = 0, int to]) that could parse a substring as a double without creating the substring.

Linq to split/analyse substrings

I have got a List of strings like:
String1
String1.String2
String1.String2.String3
Other1
Other1.Other2
Test1
Stuff1.Stuff1
Text1.Text2.Text3
Folder1.Folder2.FolderA
Folder1.Folder2.FolderB
Folder1.Folder2.FolderB.FolderC
Now I would like to group this into:
String1.String2.String3
Other1.Other2
Test1
Stuff1.Stuff1
Text1.Text2.Text3
Folder1.Folder2.FolderA
Folder1.Folder2.FolderB.FolderC
If
"String1" is in the next item "String1.String2" I will ignore the first one
and if the second item is in the third I will only take the third "String1.String2.String3"
and so on (n items). The string is structured like a node/path and could be split by a dot.
As you can see for the Folder example Folder2 has got two different Subfolder items so I would need both strings.
Do you know how to handle this with Linq? I would prefer VB.Net but C# is also ok.
Regards Athu
Dim r = input.Where(Function(e, i) i = input.Count - 1 OrElse Not input(i + 1).StartsWith(e + ".")).ToList()
Condition within Where method checks if element is last from input or is not followed by element, that contains current one.
That solution uses the fact, that input is List(Of String), so Count and input(i+1) are available on O(1) time.
LINQ isn't really the correct approach here, because you need to access more than one item at a time.
I would go with something like this:
public static IEnumerable<string> Filter(this IEnumerable<string> source)
{
string previous = null;
foreach(var current in source)
{
if(previous != null && !current.Contains(previous))
yield return previous;
previous = current;
}
yield return previous;
}
Usage:
var result = strings.Filter();
Pretty simple one. Try this:
var lst = new List<string> { /*...*/ };
var sorted =
from item in lst
where lst.Last() == item || !lst[lst.IndexOf(item) + 1].Contains(item)
select item;
the following simple line can do the trick, I'm not sure about the performance cost through
List<string> someStuff = new List<string>();
//Code to the strings here, code not added for brewity
IEnumerable<string> result = someStuff.Where(s => someStuff.Count(x => x.StartsWith(s)) == 1);

Resources