I have this quite long string that contains multiple information. So I guess we can say that its a couple of fields concatenated together without any delimiters. I understand that to make this work, all of the lengths of the fields should always be fixed. However, two of the fields represent a name and an amount and no prefixes/suffixes were implemented to maintain a fixed length.
I was wondering how would I got about this problem? Here's a sample of the string and how they should be separated:
Sample #1
Actual Input:
48001MCAbastillas2200800046300017100518110555130000123
How it should be separated:
480 | 01 | MCAbastillas | 2200800046300017 | 100518 | 110555 | 130000 | 123
Sample #2
Actual Input:
48004MCAbastillas22008000463000171005181105555000000123
How it should be separated:
480 | 04 | MCAbastillas | 2200800046300017 | 100518 | 110555 | 5000000 | 123
In my example only the amount has changed but I'm expecting that the name will vary in length as well. Any suggestion will be much appreciated.
I'd probably use a regular expression for this.
String test = "48004MCAbastillas22008000463000171005181105555000000123";
Pattern pattern = Pattern.compile("^(\\d{3})(\\d{2})([A-Za-z]+)(\\d{16})(\\d{6})(\\d{6})(\\d+)(\\d{3})$");
Matcher matcher = pattern.matcher(test);
if (matcher.matches())
{
for (int i = 1; i <= matcher.groupCount(); ++i)
{
System.out.print(matcher.group(i) + " | ");
}
}
Sample output:
480 | 04 | MCAbastillas | 2200800046300017 | 100518 | 110555 | 5000000
| 123 |
Note that the third and second to last groups do not have fixed lengths.
It's more difficult if the name can contain numbers. My approach would be to run this against the data that you have and print a list of anything that doesn't match (i.e. add an else clause). Perhaps then you can come up with a better strategy for handling these cases. For example, something like ([A-Za-z]+\w*[A-Za-z]+) might be an improvement, because that will at least allow numbers in the middle of the name.
Sometimes you just have to accept that when the data you're given is crap, you just have to do the best that you can and that might mean throwing some of it away.
We want the output
480 | 01 | MCAbastillas | 2200800046300017 | 100518 | 110555 | 130000
| 123
where the fields 3 and 7 had no fixed length.
Suppose that we store the string in a string var:
String s="48001MCAbastillas2200800046300017100518110555130000123";
We can find the fields 1 & 2 easly:
System.out.println(s.substring(0, 3)); //has 3 digit
System.out.println(s.substring(3, 5)); //has 2 digit
//we can reduce s
s=s.substring(6); //remove char from 0 to 5 included
If you'll call System.out.println(s); you well see
CAbastillas2200800046300017100518110555130000123
Now we have the string... I can deduce that it is composed only by char. So we have to find the first occurrence of a number... We can use a cycle:
int index=-1;
for( int i=0; i<s.length(); i++ ) {
if( Character.isDigit(s.charAt(i))) {
index=i;
System.out.println("There is a number in the position "+ index);
break;
}
}
Now you can extract your name with:
System.out.println(s.substring(0, index));
and extract the other 3 fields (you can optimize this part...)
System.out.println(s.substring(0, 16));
s=s.substring(16);
System.out.println(s.substring(0, 6));
s=s.substring(6);
System.out.println(s.substring(0, 6));
s=s.substring(6);
Finally, you can divide the remaining s in two part with length s.length.3 and 3:
System.out.println(s.substring(0, s.length()-3));
System.out.println(s.substring( s.length()-3,s.length()));
Your output will be:
480
01
There is a number in the position 11
CAbastillas
2200800046300017
100518
110555
130000
123
Related
How can I get substring dynamically, I want to split one word into two parts one is a string and other to no,
AA112 this is my string so from sql query
SELECT substr(thisColumn, 1,2) AS String from thisTable
I am getting AA in the query the index(2) I am pasing is dynamic I am getting from some value, So here I am able to get the string now I want to get the number +1 like it is 112 then -> 113
I have tried several queries but it is not working, I have tried doing it with javascript substring but it didn't work out.
Sample output
AAA123 -> AAA and 124
AA4 -> AA and 5
BBBB8 -> BBBB and 9
const input="AA112";
var numberPattern = /\d+/g;
const number = input.match(numberPattern)[0];
const text = input.replace(number,"");
console.log(text); //AA
console.log(number); //112
const incremented = parseInt(number) + 1;
console.log(incremented);
Using LOCATE, IF,LEAST and SUBSTRING over two sub-query can achieve the output result you're looking for.
SELECT VAL,
SUBSTRING(VAL,1,FIRSTNUM-1),
SUBSTRING(VAL,FIRSTNUM,999)+1
FROM
(SELECT VAL,LEAST(V0+0,V1+0,V2+0,V3+0,V4+0,V5+0,V6+0,V7+0,V8+0,V9+0) FIRSTNUM FROM
(SELECT VAL,
IF(LOCATE(0,VAL)=0,999,LOCATE(0,VAL)) V0,
IF(LOCATE(1,VAL)=0,999,LOCATE(1,VAL)) V1,
IF(LOCATE(2,VAL)=0,999,LOCATE(2,VAL)) V2,
IF(LOCATE(3,VAL)=0,999,LOCATE(3,VAL)) V3,
IF(LOCATE(4,VAL)=0,999,LOCATE(4,VAL)) V4,
IF(LOCATE(5,VAL)=0,999,LOCATE(5,VAL)) V5,
IF(LOCATE(6,VAL)=0,999,LOCATE(6,VAL)) V6,
IF(LOCATE(7,VAL)=0,999,LOCATE(7,VAL)) V7,
IF(LOCATE(8,VAL)=0,999,LOCATE(8,VAL)) V8,
IF(LOCATE(9,VAL)=0,999,LOCATE(9,VAL)) V9 FROM mytable) A ) B;
Here I use LOCATE to find the location of the number occurrence in the value then REPLACE to change the value to 999 if it returns 0. This is essential for the next operation using LEAST because if I leave it 0, it'll return all 0 instead. The reason I use LEAST is because if you look at the 4th data example in the fiddle it's AAAAA321. This will return the result in grid like the following:
+----------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| VAL | V0 | V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 | V9 |
+----------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| AAA123 | 999 | 4 | 5 | 6 | 999 | 999 | 999 | 999 | 999 | 999 |
| AA4 | 999 | 999 | 999 | 999 | 3 | 999 | 999 | 999 | 999 | 999 |
| BBBB8 | 999 | 999 | 999 | 999 | 999 | 999 | 999 | 999 | 5 | 999 |
| AAAAA321 | 999 | 8 | 7 | 6 | 999 | 999 | 999 | 999 | 999 | 999 | <---this
| AAA45 | 999 | 999 | 999 | 999 | 4 | 5 | 999 | 999 | 999 | 999 |
+----------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
The first number occurrence is actually '3' but because I construct the query running from 0-9, I'll always get the first number in front (in this case '1' is the 8th occurrence) despite it being on the middle or last position. That's why LEAST will correctly take which number is actually located first using LOCATE function.
In the last outer query, I use the result from the LEAST function (assigned as FIRSTNUM) as the defining value for the SUBSTRING. The first substring I use it as the end location subtract by 1 to get the strings and in the second substring I use it as the first location to get the number (I end the location with 999).
Fiddle: https://www.db-fiddle.com/f/F15cxiYJxGcozYUbQukeB/5
Edit: I realized I cannot use REPLACE because if the location is like 10, it will replace 0 to 999 which makes it become 1999 instead. So I use IF.
I could create a bitwise trie that just looks like this:
x
_____________|___________
| |
___●___ ___□___
| | | |
_■ _○ _■ □_
| | | |
_■ __■__ ____●___ ○____
| | | | | |
● ● □_ ● _○_ ___□
| | | |
○ ● ○ __■
|
●
However, I would like to try something different. Instead of doing binary tries (bitwise tries) -- which are based on taking 1 bit at a time and choosing the next 1 of 2 slots to visit -- I would like to use 2 bits at a time, or 3 bits at a time, etc. Using 2 bits at a time would create a trie that has 4 branches. Using 3 bits, it would have 8 branches. This would be nice to use to compact the trie a little bit.
So I'm wondering how to do that. How to take an integer and essentially slice off 2 or 3 or n bits at a time. So given an integer like this:
10010110
That is 150 in binary.
I would like to get let's say 2 bytes at a time, so:
10
01
01
10
That would mean I put it in slot 2, then 1, then 1, then 2. Or if I chose 4 bits, then:
1001
0110
That would put it in slot 9 then slot 6.
So the question is, how to implement a function sort of like this:
function sliceInteger(integer, start, length) {
return integer[start..length]
}
var x = sliceInteger(150, 4, 4) // => 6
You could just use bitwise arithmetic:
function sliceInteger(integer, start, length) {
return (integer >> start) & ((1 << length) - 1);
}
console.log(sliceInteger(150, 4, 4));
Edit
I notice that in your question you are slicing right to left i.e. MSB to LSB, whereas the function I've written above slices left to right i.e. LSB to MSB, hence it returns 9 where your suggested result is 6. If that is the way you want to slice, you should use this function instead. Note that if you want to slice longer than 8-bit integers, you will need to change the 8 in the code appropriately.
function sliceInteger(integer, start, length) {
return (integer >> (8 - start - length)) & ((1 << length) - 1);
}
console.log(sliceInteger(150, 4, 4));
you can convert number to binary string and splice it then convert that to decimal number
function sliceInteger(integer, start, length) {
var binary = integer.toString(2)
binary = binary.slice(start, start+length)
return parseInt(binary, 2)
}
console.log(sliceInteger(150, 4, 4))
I am new to MySQL so describing problems in words is difficult and searching for solutions is extremely challenging.
This problem is best explained visually:
I want to select (as an array) exchange_pair_id's that share the same pair_id.
So in the above data, my MySQL query would return an object:
{ pair_id: 1, exchange_pair_id: [183, 1] }
I am aware this is a butchered question, but I do not know the words to search to solve this problem.
Updated for clarity/brevity:
+------------------+-------------+---------+
| exchange_pair_id | exchange_id | pair_id |
+------------------+-------------+---------+
| 1 | 3 | 1 |
+------------------+-------------+---------+
| 183 | 1 | 1 |
+------------------+-------------+---------+
| 69 | 2 | 2 |
+------------------+-------------+---------+
| 12 | 4 | 2 |
+------------------+-------------+---------+
| 2 | 3 | 2 |
+------------------+-------------+---------+
| 3 | 3 | 3 |
+------------------+-------------+---------+
Desired output from a Javascript MySQL select query:
[
{ pair_id: 1, exchange_pair_id: [1, 183] },
{ pair_id: 2, exchange_pair_id: [69, 12, 2] },
{ pair_id: 3, exchange_pair_id: [3] }
]
I am thinking a query like this , but I'm waiting your answer at comments.
Basically, you use GROUP BY to obtain in two different columns the values for each pair_id:
SELECT pair_id, MIN(exhange_pair_id) AS id1, MAX(exchange_pair_id) AS id2
FROM yourtable
GROUP BY pair_id;
Update version: Can you try this please on your data?
In this case MYSQL let you concat field using a separator (,)
SELECT pair_id, GROUP_CONCAT(exhange_pair_id) AS exhange_pair_id
FROM yourtable
GROUP BY pair_id
try select exchange_pair_id from yourtable where pair_id=1 then it will return array [1,183]
The SQL you are looking for would be:
SELECT * WHERE pair_id == 1
Without knowing what your specific code looks like, I can only guess as to how you are implementing a call to your database. I would assume you are doing some sort of async call to a PHP controller. So instead of using '1' in the query, you will need to use whatever variable you are pulling from your code to know what you are looking for.
I was practicing my javascript with CodeFights and after I finished an exercise I saw this function as a result:
// Subject :
// Several people are standing in a row and need to be divided into two teams.
// The first person goes into team 1, the second goes into team 2,
// the third goes into team 1 again, the fourth into team 2, and so on.
// You are given an array of positive integers - the weights of the people.
// Return an array of two integers, where the first element is the total weight of
// team 1, and the second element is the total weight of team 2
// after the division is complete.
// Example :
// For a = [50, 60, 60, 45, 70], the output should be
// alternatingSums(a) = [180, 105].
// answer
alternatingSums = a => a.reduce((p,v,i) => (p[i&1]+=v,p), [0,0])
I don't understand what p[i&1]+=v,p means.
The & symbol is a bitwise binary operator.
To understand what would happen, you have to convert each item to binary.
| i (decimal) | i (binary) | i & 1 |
|-------------|------------|-------|
| 0 | 0 | 0 |
| 1 | 1 | 1 |
| 2 | 10 | 0 |
| 3 | 11 | 1 |
| 4 | 100 | 0 |
| 5 | 101 | 1 |
Effectively, every even number will be transformed to 0, and every odd number will be transformed to 1.
If I was trying to achieve that outcome, I personally would have used the modulus operator (%)
p[i%2] += v;
But that's just me.
The other part is that there are two statements separated by a comma:
(p[i&1]+=v,p)
That's saying "Perform this action, then return p. It's shorthand for:
alternatingSums = a => a.reduce((p,v,i) => {
p[i&1]+=v;
return p;
},
[0,0])
It looks for an element of the p array that has index of i&1 - it is a bitwise AND operation. Then, increments its value by a value of v variable. Finally, returns the value of p variable.
What does the +d in
function addMonths(d, n, keepTime) {
if (+d) {
mean?
The + operator returns the numeric representation of the object. So in your particular case, it would appear to be predicating the if on whether or not d is a non-zero number.
Reference here. And, as pointed out in comments, here.
Operator + is a unary operator which converts the value to a number. Below is a table with corresponding results of using this operator for different values.
+----------------------------+-----------+
| Value | + (Value) |
+----------------------------+-----------+
| 1 | 1 |
| '-1' | -1 |
| '3.14' | 3.14 |
| '3' | 3 |
| '0xAA' | 170 |
| true | 1 |
| false | 0 |
| null | 0 |
| 'Infinity' | Infinity |
| 'infinity' | NaN |
| '10a' | NaN |
| undefined | NaN |
| ['Apple'] | NaN |
| function(val){ return val }| NaN |
+----------------------------+-----------+
Operator + returns a value for objects which have implemented method valueOf.
let something = {
valueOf: function () {
return 25;
}
};
console.log(+something);
It is a unary "+" operator which yields a numeric expression. It would be the same as d*1, I believe.
As explained in other answers it converts the variable to a number. Specially useful when d can be either a number or a string that evaluates to a number.
Example (using the addMonths function in the question):
addMonths(34,1,true);
addMonths("34",1,true);
then the +d will evaluate to a number in all cases. Thus avoiding the need to check for the type and take different code paths depending on whether d is a number, a function or a string that can be converted to a number.