How can I split the below string into a 2dimensional-array: - javascript

How can I split the below string into a 2dimensional-array:
Customer::Europe|UK|Scotland|Product::Drinks|Water|
array:
[Customer][Europe]
[Customer][UK]
[Customer][Scotland]
[Product][Drinks]
[Product][Water]
Not sure how to create the array. Haven't coded in years, so be kind
hArray= [];
vArray= [];
var i = j = 0;
var count = hierarchy.search(/[:|]+/);
write(hierarchy);
while (count > 0) {
if (hierarchy.indexOf(":") < hierarchy.indexOf("|") || (hierarchy.indexOf(":") > 0 && hierarchy.indexOf("|") == -1) ) {
hArray[j] = hierarchy.substr(0,hierarchy.indexOf(":"));
hierarchy = hierarchy.slice(hierarchy.indexOf(":")+2);
count = hierarchy.search(/[:|]+/);
j++;
} else
if (hierarchy.indexOf("|") < hierarchy.indexOf(":") {
vArray[i] = hierarchy.substr(0,count);
hierarchy = hierarchy.slice(count+1);
count = hierarchy.search(/[:|]+/);
i++;
}
if (count == -1) break;
//create multiArray ?
}

var source = "Customer::Europe|UK|Scotland|Product::Drinks|Water|";
var parts = source.split(/(\w+::)/);
var result = [];
for (var i = 1; i < parts.length; i += 2) {
var key = parts[i].replace("::", "");
var values = parts[i + 1].split("|");
for (var j = 0; j < values.length - 1; ++j) {
var line = new Array(2);
line[0] = key;
line[1] = values[j];
result.push(line);
}
}
console.log(result);

You can use Array.reduce like this. First, we split on | that is behind any owrd followed by ::. Then we reduce it, by using an array as memo and push an array into the memo, which we finally return.
var arr = input.split(/\|(?=\w+::)/).reduce(function(arr, str){
var array = str.split('::');
return arr.push(str.split('::')[1].split('|').filter(String).map(function(s){
return [array[0], s]
})), arr;
}, []);

Related

how to get common substring in two string to maintain order?

I am trying to do one problem of hackerrank but I am not able to solve that problem
Can someone please help me with wrong logic implementation done by me?
problem
Print the length of the longest string, such that is a child of both s1 and s2.
Sample Input
HARRY
SALLY
Sample Output
2
Explanation
The longest string that can be formed by deleting zero or more characters from HARRY and SALLY is AY, whose length is 2.
Sample Input 1
AA
BB
Sample Output 1
0
Explanation 1
AA and BB have no characters in common and hence the output is 0
Sample Input 2
SHINCHAN
NOHARAAA
Sample Output 2
3
Explanation 2
The longest string that can be formed between SHINCHAN and NOHARAAA while maintaining the order is NHA.
I have written some logic which is as follows:
function commonChild(s1, s2) {
var arr = s2.split(),
currenString = '',
maxLength = 0,
index = -1;
console.log(arr);
for (var i = 0; i < s1.length; i++) {
var char = s1.charAt(i),
charIndex = arr.indexOf(char);
console.log(char)
if (index < charIndex) {
index = charIndex;
currenString +=char;
}
maxLength= Math.max(maxLength,currenString.length)
}
return maxLength;
}
commonChild('ABCDEF', 'FBDAMN');
console.log(commonChild('ABCDEF', 'FBDAMN'));
pardon me. this is an unoptimized solution.
function maxCommon(a, b, offset) {
offset = offset || 0;
if (a === b) {
return [[a, b]];
}
var possibleSolns = [];
for (var i = 0 + offset; i < a.length; i++) {
for (var j = 0 + offset; j < b.length; j++) {
if (a.charAt(i) === b.charAt(j)) {
possibleSolns.push([
a.substring(0, offset) + a.substring(i),
b.substring(0, offset) +b.substring(j)
]);
break;
}
}
}
var results = [];
possibleSolns.forEach(function(soln) {
var s = maxCommon(soln[0], soln[1], offset+1);
if (s.length === 0) {
s = [[soln[0].substring(0, offset +1), soln[1].substring(0, offset +1)]];
}
results = results.concat(s);
});
return results;
}
var maxLen = -1;
var soln = null;
maxCommon("ABCDEF", "FBDAMN").map(function(_) {
return _[0];
}).forEach(function(_) {
if (_.length > maxLen) {
soln = _;
maxLen = _.length;
}
});
console.log(soln);
I kept most of your logic in the answer:
function commonChild(s1, s2) {
var // Sets strings to arrays
arrayString1 = s1.split(""),
arrayString2 = s2.split(""),
collectedChars = "",
maxLength = 0,
max = arrayString1.length;
for (var i = 0; i < max; i++) {
var
char = arrayString1[i],
count = arrayString2.indexOf(char);
// check if char is in second string and not in collected
if (count != -1 && collectedChars.indexOf(char) == -1) {
collectedChars += char;
maxLength++;
}
}
return maxLength;
}
// expected output 4
console.log(commonChild(
'ABCDEF',
'FBDAMN'
));
// expected output 1
console.log(commonChild(
'AA',
'FBDAMN'
));
Using lodash and spread operation you can do it in this way.
const test = (first, second) => {
const stringArray1 = [...first];
const stringArray2 = [...second];
return _.intersection(stringArray1, stringArray2).length;
}
console.log(test('ABCDEF', 'FBDAMN'));
You can solve it using lcs least common subsequence
function LCS(s1,s2,x,y){
var result = 0;
if(x==0 || y==0){
result = 0
}else if(s1[x-1] == s2[y-1]){
result = 1+ LCS(s1,s2,x-1,y-1)
} else if(s1[x-1] != s2[y-1]){
result = Math.max(LCS(s1,s2,x-1,y), LCS(s1,s2,x,y-1))
}
return result;
}
// Complete the commonChild function below.
function commonChild(s1, s2) {
return LCS(s1,s2,s1.length,s2.length);
}
Based on your code before the edit.
One little change is to change var arr = s2.split() to split('').
The main change in the logic is that I added a loop to run over the string each time from another character (first loop from the first, second from the second etc).
function commonChild(s1, s2) {
var arr = s2.split(''),
currenString = '',
maxLength = 0,
index = -1,
j = -1;
for (var ii = 0; ii < s1.length; ii++) {
index = -1;
currenString = '';
for (var i = ii; i < s1.length; i++) {
var char = s1.charAt(i),
j = arr.indexOf(char);
if (index < j) {
index = j;
currenString += char;
}
maxLength = Math.max(maxLength, currenString.length)
}
}
return maxLength;
}
console.log(commonChild('ABCDEF', 'FBDAMN'));

How do I build an object counting occurrences in an Array in JavaScript?

I want to count how often a number in an Array occurs. For example, in Python I can use Collections.Counter to create a dictionary of how frequently an item occurs in a list.
This is as far as I've gotten in JavaScript:
var array = [1,4,4,5,5,7];
var obj = {};
for (var i=0; i < array.length; i++) {
/* obj[array[i]] = +=1 */ <= pseudo code
}
How can I create this frequency counter object?
Close but you can't increment undefined so you need to set initial value if it doesn't exist
var array = [1,4,4,5,5,7];
var obj = {};
for (var i=0; i < array.length; i++) {
obj[array[i]] = (obj[array[i]] || 0) +1 ;
}
You were almost there. See below code:
var array = [1,4,4,5,5,7];
var obj = {};
for (var i=0; i < array.length; i++) {
obj[array[i]] = (obj[array[i]] || 0 ) +1;
}
console.log(obj);
Create an object and check if that specific key exist.If exist then increase it's value by 1
var array = [1, 4, 4, 5, 5, 7];
var obj = {};
for (var i = 0; i < array.length; i++) {
if (obj.hasOwnProperty(array[i])) {
obj[array[i]] += 1;
} else {
obj[array[i]] = 1;
}
}
console.log(obj)
You can use the ? : ternary operator to set initial value as 1 and then increment it on subsequent matches.
var array = [1,4,4,5,5,7];
var obj = {};
for (var i=0; i < array.length; i++) {
obj[array[i]] = obj[array[i]]?obj[array[i]]+1:1;
}
console.log(obj);
If the array is always going to be same, and you are going to check frequency of multiple items in the same array without it it being modified, #JohanP's answer is good.
But if you are only going to check frequency of only one item, or the array can change, creating the object is nothing but extra overhead.
In that case, you can do something like this:
const getItemFrequency = function(array, item) {
return array.filter(i => i === item).length;
}
var array = [1,4,4,5,5,7];
console.log(getItemFrequency(array, 4));
Concise logic written as proper function:
function countArrayItemFrequecy(array) {
const length = array.length;
const map = {};
for ( let i = 0; i < length; i++ ) {
let currentItem = array[i];
if (typeof map[currentItem] !== 'undefined' ) {
map[currentItem]++
} else {
map[currentItem] = 1
}
}
return map;
}
You need to make sure to assign default value to your frequency object for the first occurrence of the item. As a shortcut you can use ternary operator
var array = [1,4,4,5,5,7];
var obj = {};
for (var i=0; i < array.length; i++) {
obj[array[i]] = obj[array[i]] ? obj[array[i]]++ : 1;
}
which is the same as:
var array = [1,4,4,5,5,7];
var obj = {};
for (var i=0; i < array.length; i++) {
if (obj[array[i]]) {
obj[array[i]]++;
} else {
obj[array[i]] = 1;
}
}
You can use Object.assign: below clones map and then increments/adds the counter. These are pure (no side effects/param reassignment), single-purpose functions.
addToMap does the same thing as { ...map, map[e]: [e]: (map[e] || 0) + 1 }, but that requires babel.
const addToMap = (map, e) => Object.assign({}, map, { [e]: (map[e] || 0) + 1 });
const buildMap = a => a.reduce(addToMap, {});
Using Array.reduce:
arr.reduce(function (acc, item) {
acc[item] = (acc[item] || 0) + 1;
return acc;
}, {});
Example:
var arr = [1,1,2,4,1,4];
var counts = arr.reduce(function (acc, item) {
acc[item] = (acc[item] || 0) + 1;
return acc;
}, {});
console.log(counts);

Find out if array contains arithmetic progression in javascript

I have an array:
var myarray = [1,2,3,4,7,9,12,13,14]
I need to group values like so:
var array_1 = 1,2,3,4
var array_2 = 7
var array_3 = 8
var array_4 = 12,13,14
I need to find a sequences with an arithmetic progression and seperate from other values.
Any ideas?
Check out this solution
function explode(myarray)
{
var multi = [];
var i = j = 0;
for ( key in myarray )
{
if((myarray[key-1]) != (myarray[key]-1))
{
i++;
j=0;
}
if(j==0)
multi[i] = [];
multi[i][j] = myarray[key];
j++;
}
return multi;
}
It returns a multidimentionnal array that you can use in your example like this
var myarray = [1,2,3,4,7,9,12,13,14];
var multi_array = explode(myarray);
var array_1 = multi_array[0];
var array_2 = multi_array[1];
var array_3 = multi_array[2];
var array_4 = multi_array[3];
New update :
You can also remove the j index and use .push to add new elements to your array
function explode(myarray)
{
var multi = [];
var i = 0;
for ( key in myarray )
{
if((myarray[key-1]) != (myarray[key]-1))
i++;
if(!multi[i])
multi[i] = [];
multi[i].push(myarray[key]);
}
return multi;
}
The following seems to work, but displays a slightly different output than the one you expect.
In your example, I think 7 and 9 should be grouped (any sequence of two items is an arithmetic
progression after all). Or if they are not grouped, then 12 should not be grouped with 13 and
14 either, since 12-9 != 13-12
function split(arr) {
if (arr.length < 2) {
return;
}
var delta = undefined;
var start = 0;
for (var idx = 1; idx < arr.length; idx++) {
if (delta === undefined) {
delta = arr[idx] - arr[idx - 1];
}
if (arr[idx] - arr[idx - 1] != delta) {
alert("subarray " + arr.slice(start, idx));
start = idx;
delta = undefined;
}
}
alert("subarray from" + arr.slice(start, arr.length));
}
split([1,2,3,4,7,9,12,13,14]);
arrays = Array();
var c = 0;
array[c][] = myarray[0]);
for (var i = 1; i<myarray.length; i++) {
if (myarray[i-1] +1 != myarray[i])
c++;
array[c][] = push(myarray[i]);
}
not sure the array syntax (might mix up languages here) is correct or whether I understand your problem fully.

How to count the number of times variables repeats in a javascript array?

How do I get the array-members and the number of times they repeat (recurrences)?
I currently have this script
//COUNT VAL
var curr = '';
var previous = '';
var arr = new Array();
var sorted = count.sort();
for(var c=0; c < sorted.length; c++){
if(sorted[c] != ''){
if(sorted[c] != curr){
var repeat = 1;
arr[sorted[c]] = repeat;
curr = sorted[c];
}
else if(sorted[c] == curr){
repeat++;
}
}
}
alert(JSON.stringify(arr));
The values of the array "count" are (I used JSON.stringify):
[" 2"," 2"," 2","1","1","1","1","1","1","1","1","1","1",null,null,null,null,null,null,null,null,null,null,null,null,null]
What I expect my script to display... (Im expecting it to return an array)
[1: 10, 2: 3]
(x: y) x is the number, y is the number of times it repeated.
What I get...
[null,1,1]
var a = [" 2"," 2"," 2","1","1","1","1","1","1","1","1","1","1",null,null,null,null,null,null,null,null,null,null,null,null,null];
var counts = a.reduce( function(obj, cur){
if( !obj[cur] ) {
obj[cur] = 0;
}
obj[cur]++;
return obj;
}, {});
Result
2: 3
1: 10
null: 13
This will give you the summary, ignoring null values
var collection = [" 2"," 2"," 2","1","1","1","1","1","1","1","1","1","1",null,null,null,null,null,null,null,null,null,null,null,null,null];
var summary = collection.reduce(function(a, b) {
var tmp = parseInt(b)
if (!isNaN(tmp)) {
if (!a[tmp]) {
a[tmp] = 0;
}
a[tmp]++;
}
return a;
}, {});
console.log(summary);
Using your code,
Modify your loop like this,
for(var c=0; c < sorted.length; c++){
if(sorted[c] != ''){
if(arr[sorted[c]] ){
var count = arr[sorted[c]];
count++;
arr[sorted[c]] = count;
}
else{
arr[sorted[c]] = 1;
}
}
}
Not sure if its best possible solution, but it works and save output in array.
var arr = [" 2"," 2"," 2","1","1","1","1","1","1","1","1","1","1",null,null,null,null,null,null,null,null,null,null,null,null,null];
var obj = {};
var final = [];
var count = 0;
for(var i=0,len=arr.length;i<len;i++){
if(arr[i] in obj){
final[obj[arr[i]]] ++;
}
else{
obj[arr[i]] = count;
final[count] = 1;
count++;
}
}
console.log(final);
Try this:
var repeated = function repeated(arr){
var res = {};
for(index in arr){
var x = arr[index];
if(!res.hasOwnProperty(x))
res[x] = 0;
res[x]++;
}
return res;
}

Using Javascript find array values in another array and in order

Here is one to get your brain going! I've not had any luck with it.
[1,2,1,1,2,1,1,1,2,2]
[1,2,1,1,2,1]
I would like to use the second array to find the values in the first, but they must be in the same order.
Once for I would like it to return the next key up from the last key in the second array.
So in this example it would use the first six digits in the first array and then return 6 as the key after the final one in the second array.
var a2 = [1,2,1,1,2,1,1,1,2,2]
var a1 = [1,2,1,1,0,1]
function find(arr1, arr2) {
var len = 1
var result = 0;
var s2 = arr2.toString();
for (len=1;len <= a1.length; len++)
{
var aa1 = arr1.slice(0, len)
var s1 = aa1.toString();
if(s2.indexOf(s1)>=0){
result = aa1.length;
}
else {
break;
}
}
return result;
}
alert(find(a1, a2));
var find = function(haystack, needle) {
var doesMatch = function(offset) {
for (var i = 0; i < needle.length; i++) {
if (haystack[i+offset] !== needle[i]) {
return false;
}
}
return true;
};
for (var j=0; j < haystack.length - needle.length; j++) {
if (doesMatch(j)) {
return j;
}
}
return -1;
};
This is quick, this is dirty, and this is correct only if your data doesn't include any comma.
var needle = [1,2,1,1,2,1];
var haystack = [1,2,1,1,2,1,1,1,2,2];
if ( needle.length <= 0 ) return 0;
var fromStr = ','+haystack.toString()+','
var findStr = ','+needle.toString()+','
// Find ',1,2,1,1,2,1,' in ',1,2,1,1,2,1,1,1,2,2,'
var pos = fromStr.indexOf(findStr);
// Count the end position requested
return pos >= 0 ? fromStr.slice(0,pos+1).match(/,/g).length + needle.length - 1 : -1;
Note: The comma at head and tail is to make sure [22,12] doesn't match [2,1].

Categories

Resources