Why is white space not found in my NodeJS program? - string

For some obscure reason, my str.split(" ") command doesn't seem to work. I've been trying to debug the situation for a while now and can't seem to find the solution. Let me start off by saying that, unfortunately, I can't replicate the error. I've tried creating a JSFiddle, but it works correctly.
Here's my problem: I've got a JSObject "library" over which I'm looping to create MongoDocuments and during this "construction" I get the following:
if (payload[i].asking) {
let price = payload[i].asking
price = price.substring(1, price.length);
console.log(price);
console.log(price.indexOf(" "));
const priceArr = price.split(" ");
console.log(priceArr);
price = priceArr[0];
currency = priceArr[1];
listing.set('asking', price);
listing.set('currency', currency);
}
where:
payload is the full JSObject "library"
[i] the current JSObject
and asking, the key I'm working on, in this particular place of the code.
And here's the result:
500.00 eur
-1
[ '500.00 eur' ]
950.00 eur
-1
[ '950.00 eur' ]
5,000.00 usd
-1
[ '5,000.00 usd' ]
250.00 usd
-1
[ '250.00 usd' ]
800.00 usd
-1
[ '800.00 usd' ]
899.00 usd
-1
[ '899.00 usd' ]
3,500.00 usd
-1
[ '3,500.00 usd' ]
2,800.00 usd
-1
[ '2,800.00 usd' ]
2,250.00 usd
-1
[ '2,250.00 usd' ]
3,750.00 usd
-1
[ '3,750.00 usd' ]
1,500.00 usd
-1
[ '1,500.00 usd' ]
5,800.00 usd
-1
[ '5,800.00 usd' ]
2,500.00 usd
-1
[ '2,500.00 usd' ]
So I understand why price.split(" ") doesn't work: I apparently have no white space in the first place (indexOf(" ") === -1) but I'm not sure why and what's happening. payload[i].asking is a string alright (price.substring proves it) but I don't understand why this white space doesn't exist.

OK so I found an alternative, using regex, even though it doesn't solve the exact problem I describe per se:
const priceArr = price.split(/(\s+)/)
It might help someone else...

Related

How to allocate a value that changes while execution in vim (lightline plugin)?

I'm hacking on the lightline plugin of vim (downloaded version). I can modify the colors of each themes. I did something that works well in the powerline.vim scheme (path : ~/.vim/pack/plugins/start/lightline/autoload/lightline/colorscheme/powerline.vim)
Now I want the colortheme to change while I'm in vim. I added this code in the begining of powerline.vim :
10 let s:BSsplitscolor = "'darkestgreen', 'brightgreen'"
11 if g:BSsplitsbool == "1"
12 let s:BSsplitscolor = "'gray4', 'brightorange'"
13 endif
14
15 " ============================== NOTE: below : already there
16
17 let s:p = {'normal': {}, 'inactive': {}, 'insert': {}, 'replace': {}, 'visual': {}, 'tabline': {}}
18 let s:p.normal.left = [ [s:BSsplitscolor, 'bold'], ['white', 'gray4'] ]
Here s:BSsplitscolor contains the colors I want : it's either 'gray4', 'brightorange' if g:BSsplitsbool equals 1 or 'darkestgreen', 'brightgreen' if not. It's g:BSsplitsbool that changes.
Now the problem is at the 16th line : when I add s:BSsplitscolor after [ [, I get these errors when I restart vim (translate from french) :
Error detected while treating functionlightline#update[5]..lightline#colorscheme[18]..lightline#highlight :
line 18 :
E254: can not allocate color darkestgreen
E416: missing '=' : , 'brightgreen' guibg=bold ctermfg=0 ctermbg=0
Error detected while treating function lightline#update :
line 5 :
E171: missing :endif
I think I'm missing something... I'm not so good at vim scripting : I can do an if instruction, remap, and that's all.
First, the solution:
let s:BSsplitscolor = ['darkestgreen', 'brightgreen']
[...]
let s:p.normal.left = [ s:BSsplitscolor + ['bold'], ['white', 'gray4'] ]
Second, the explanation:
You are trying to build a list of three items:
['darkestgreen', 'brightgreen', 'bold']
out of a string that vaguely looks like a list:
"'darkestgreen', 'brightgreen'"
and a list with a single string:
['bold']
by inserting that string in that list:
[ s:BSsplitscolor, 'bold']
which gives you this monstrosity:
['''darkestgreen'', ''brightgreen''', 'bold']
which is a list of two items, not at all what you are trying to build. I'm not aware of a scripting language where something like that could be expected to work.
The actual solution is to make s:BSsplitscolor a list:
let s:BSsplitscolor = ['darkestgreen', 'brightgreen']
and merge it with ['bold']. This can be done in several ways. With :help expr-+:
let s:p.normal.left = [ s:BSsplitscolor + ['bold'], ['white', 'gray4'] ]
or with :help extend():
let s:p.normal.left = [ extend(s:BSsplitscolor, ['bold']), ['white', 'gray4'] ]

MSSQL module converting return value to int?

We are using the MSSQL module with Node.js.
I am running the following query:
SELECT AVG((RAT_VALUE * 1.0)) FROM RAT WHERE RAT_PER_ID_FROM IS NOT NULL AND RAT_PER_ID_ABOUT = 139 AND RAT_USE = 'Y' AND RAT_ABOUT_ROLE = 'RS' AND RAT_DATE_INSERTED >= '10/1/2018' AND RAT_DATE_INSERTED < '10/1/2019'
If I run this against the database directly, it returns:
4.45
The output from MSSQL is:
4
The exact resultset returned is:
results { recordsets: [ [ [Object] ] ],
recordset: [ { '': 4 } ],
output: {},
rowsAffected: [ 1 ] }
In other words, MSSQL is always returning the value 4, instead of 4.45.
The column type od RAT_VALUE is INT in the database but I've tried changing it to DECIMAL(5, 2) without any luck.
I've tried explicitly returning a DECIMAL from the query like:
SELECT CAST(AVG((RAT_VALUE * 1.0)) AS DECIMAL(5, 2)) ...
But no luck there either.
It seems MSSQL is simply clipping and dropping the decimal part of any number, even numbers of Decimal types.
I even set the value as 4.75 in the database and returned it directly and it still returns 4.
Any ideas out there?

How to sum map values based on two keys?

I have a map with two keys (customer and price) like the one shown below:
[
customer: ['Clinton', 'Clinton', 'Mark', 'Antony', 'Clinton', 'Mark'],
price: [15000.0, 27000.0, 28000.0, 56000.0, 21000.0, 61000.0]
]
customer and price values are mapped by their index positione i.e first name from customer list maps with the first price and so on.
Example
Cliton price is 15000.0
Cliton price 27000.0
Mark price 28000.0
Antony price 56000.0
Clinton price 21000.0
Mark price 61000.0
I would like to sum up price grouped by names. Expected output:
Clinton price 63000
Mark price 89000
Antony price 56000
Are there any built-in functions to achieve this in Groovy, or do I need to iterate over the map and sum values by writing my own functions?
You can start with a transpose on both lists to get tuples of customer and price. From there its basically like the other answers (group by customer, build map with customer and summed up prices). E.g.:
def data = [
customer:['Clinton', 'Clinton', 'Mark', 'Antony', 'Clinton', 'Mark'],
price:[15000.0, 27000.0, 28000.0, 56000.0, 21000.0, 61000.0]
]
println(
[data.customer, data.price].transpose().groupBy{ c, p -> c }.collectEntries{ c, ps -> [c, ps*.last().sum() ] }
)
// => [Clinton:63000.0, Mark:89000.0, Antony:56000.0]
In the problems like this, we should always plan having every entry as separate object inside a list to make it intuitive and future easy manipulation in the list.
In that case the same result can be obtained in naturally
def list = [
[customer: 'Clinton', price: 15000.0],
[customer: 'Clinton', price: 27000.0],
[customer: 'Mark', price: 28000.0],
[customer: 'Antony', price: 56000.0],
[customer: 'Clinton', price: 21000.0],
[customer: 'Mark', price: 61000.0]
]
def map = list.groupBy({it.customer}).collectEntries {k, v -> [k, v.price.sum()]}
map.each {println it}
The followint creates a map of price aggregated by customer:
def vals = (0..(-1+map.customer.size()))
.collect{['name':map.customer[it], 'price': map.price[it]]}
.groupBy{it['name']}
.collectEntries{[(it.key): it.value.collect{it['price']}.sum()]}
That results in:
[Clinton:63000.0, Mark:89000.0, Antony:56000.0]
It's essentially an iteration using a range of numbers from 0 to map.customer.size() - 1, followed by a group-by with sum of values.
This version is derived from #cfrick's answer, with an alternative to the summation. Using a map with default values isn't as "functional"/declarative, but IMHO the code is arguably easier to grok later (i.e. maintenance):
Given:
def map = [
customer: ['Clinton', 'Clinton', 'Mark', 'Antony', 'Clinton', 'Mark'],
price: [15000.0, 27000.0, 28000.0, 56000.0, 21000.0, 61000.0]
]
Approach:
def getSumMap = { data ->
def result = [:].withDefault { c -> 0.0 }
[data.customer, data.price].transpose().each { c, p -> result[c] += p }
result
}
assert 63000.0 == getSumMap(map)['Clinton']
assert 89000.0 == getSumMap(map)['Mark']
assert 56000.0 == getSumMap(map)['Antony']

logstash parse complex message from Telegram

I'm processing through Telegram history (txt file) and I need to extract & process quite complex (nested) multiline pattern.
Here's the whole pattern
Free_Trade_Calls__AltSignals:IOC/ BTC (bittrex)
BUY : 0.00164
SELL :
TARGET 1 : 0.00180
TARGET 2 : 0.00205
TARGET 3 : 0.00240
STOP LOS : 0.000120
2018-04-19 15:46:57 Free_Trade_Calls__AltSignals:TARGET
basically I am looking for a pattern starting with
Free_Trade_Calls__AltSignals: ^%(
and ending with a timestamp.
Inside that pattern (telegram message)
- exchange - in brackets in the 1st line
- extract value after BUY
- SELL values in a array of 3 SELL[3] : target 1-3
- STOP loss value (it can be either STOP, STOP LOSS, STOP LOS)....
I've found this Logstash grok multiline message but I am very new to logstash firend advised it to me. I was trying to parse this text in NodeJS but it really is pain in the ass and mad about it.
Thanks Rob :)
Since you need to grab values from each line, you don't need to use multi-line modifier. You can skip empty line with %{SPACE} character.
For your given log, this pattern can be used,
Free_Trade_Calls__AltSignals:.*\(%{WORD:exchange}\)\s*BUY\s*:\s*%{NUMBER:BUY}\s*SELL :\s*TARGET 1\s*:\s*%{NUMBER:TARGET_1}\s*TARGET 2\s*:\s*%{NUMBER:TARGET_2}\s*TARGET 3\s*:\s*%{NUMBER:TARGET_3}\s*.*:\s*%{NUMBER:StopLoss}
please note that \s* equals to %{SPACE}
It will output,
{
"exchange": [
[
"bittrex"
]
],
"BUY": [
[
"0.00164"
]
],
"BASE10NUM": [
[
"0.00164",
"0.00180",
"0.00205",
"0.00240",
"0.000120"
]
],
"TARGET_1": [
[
"0.00180"
]
],
"TARGET_2": [
[
"0.00205"
]
],
"TARGET_3": [
[
"0.00240"
]
],
"StopLoss": [
[
"0.000120"
]
]
}

Grok filter for selecting and formatting certain logs lines

I am writing up a grok filter for parsing my application log which is unstructured. What i need is to look for certain lines and generate output in a specific format. e.g below are my logs
2018-05-07 01:19:40 M :Memory (xivr = 513.2 Mb, system = 3502.0 Mb, physical = 5386.7 Mb), CpuLoad (sys = 0%, xivr = 0%)
2018-05-07 01:29:40 M :Memory (xivr = 513.2 Mb, system = 3495.3 Mb, physical = 5370.1 Mb), CpuLoad (sys = 0%, xivr = 0%)
2018-05-07 05:51:19 1 :Hangup call
***2018-05-07 05:51:22 24 :Answer call from 71840746 for 91783028 [C:\xivr\es\IVR-Dialin.dtx***]
2018-05-07 05:51:30 24 :Hangup call
***2018-05-07 05:51:34 24 :Answer call from 71840746 for 91783028 [C:\xivr\es\IVR-Dialin.dtx]***
2018-05-07 00:31:21 45 :Device Dialogic Digital dxxxB12C1 [gc60.dev - Dialogic (SDK 6.0) ver 3.0.702:11646] (ThreadID: 1FF0, DriverChannel: 44)
2018-05-07 00:31:22 40 :Device Dialogic Digital dxxxB10C4 [gc60.dev - Dialogic (SDK 6.0) ver 3.0.702:11646] (ThreadID: 1B2C, DriverChannel: 39)
I need to enter only lines highlighted with *** in below format in my Kibana: Other lines should be simply ignored
Logtimestamp: 2018-05-07 05:51:22
Channel_id: 24
Source_number:
71840746
Destination_Number: 91783028
How can this be achieved?
You can explicitly write whatever is unique about that particular pattern, and use pre-defined grok patterns for the rest.
In your case, the grok pattern would be,
%{TIMESTAMP_ISO8601:Logtimestamp} %{NUMBER:Channel_id} :Answer call from %{NUMBER:Source_number} for %{NUMBER:Destination_Number} %{GREEDYDATA:etc}
It will only match following pattern,
2018-05-07 05:51:34 24 :Answer call from 71840746 for 91783028 [C:\xivr\es\IVR-Dialin.dtx]
Explanation
The syntax for a grok pattern is %{SYNTAX:SEMANTIC}.
In your filter,
%{TIMESTAMP_ISO8601:Logtimestamp} matches 2018-05-07 05:51:34
%{NUMBER:Channel_id} match 24
:Answer call from matches the string literally
%{NUMBER:Source_number} matches 71840746
%{NUMBER:Destination_Number} matches 91783028
%{GREEDYDATA:etc} matches rest of the data i.e. [C:\xivr\es\IVR-Dialin.dtx]
in that order.
Output:
{
"Logtimestamp": [
[
"2018-05-07 05:51:22"
]
],
"Channel_id": [
[
"24"
]
],
"Source_number": [
[
"71840746"
]
],
"Destination_Number": [
[
"91783028"
]
],
"etc": [
[
"[C:\\xivr\\es\\IVR-Dialin.dtx***]"
]
]
}
You can test it here.
Hope it helps.

Resources