JavaScript - Converting URL like string params to an array - javascript

I have a string like this:
var str = 'My_Type_1=SSD&My_Value_1=16GB&My_Category_1=Disk Capacity&My_Type_2=Sony
&My_Value_2=PS4&My_Category_2=Console&My_rowOrder=2,1';
The string mostly has 3 parts except the last key:
Part 1 -> My - is a Common Prefix
Part 2 -> Type or Value or Category and it can keep changing
Part 3 -> It's a numeric value binding Part 1, Part 2 and Part 3 like Spreadsheet row.
The last key is always called
My_rowOrder and it's a comma delimeted value. It specifies how to construct the output array.
In the above example, 2,1 means a key value pair of
My_Type_2=Sony&My_Value_2=PS4&My_Category_2=Console should be the first in the output array.
Using JavaScript, I would like to parse the string and create an array out of it, such that the output is:
Array
(
[ 0 ] => Array
(
[Type] => Sony
[Value] => PS4
[Category] => Console
[Row] => 2
)
[ 1 ] => Array
(
[Type] => SSD
[Value] => 16GB
[Category] => Disk Capacity
[Row] => 1
)
)
How can I do this? I am partially able to do it this way:
function StringToArray(string) {
var request = {};
var pairs = string.split('&');
for (var i = 0; i < pairs.length-1; i++) {
var pair = pairs[i].split('=');
request[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
}
//I think I am in the right track, but need assistance
}

Your example output uses associative arrays, which JavaScript doesn't have, but you can use an array of objects instead.
This example outputs an array of objects, in the order specified by the rowOrder parameter. It trims the prefix (defined by prefix), and also trims the row number from the end of the key.
This will also work with the parameters in any order - e.g. you can mix them and it will parse as necessary, and the rowOrder parameter can appear anywhere in the string (doesn't have to be at the end).
Demo
function StringToArray(string) {
var prefix = 'My_'; // set the prefix
var output = [], request = [];
var pairs = string.split('&');
var order;
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].split('=');
if (pair[0].replace(prefix, '') == 'rowOrder') {
order = pair[1];
} else {
var key = decodeURIComponent(pair[0]);
var pos = key.lastIndexOf('_');
var trimmedKey = key.substring(0, pos).replace(prefix, '');
var row = key.substring(pos + 1);
var value = decodeURIComponent(pair[1]);
var found = false;
for (var j = 0; j < output.length; j++) {
if (output[j].Row == row) {
output[j][trimmedKey] = value;
found = true;
}
}
if (!found) {
var obj = { 'Row': row };
obj[trimmedKey] = value;
output.push(obj);
}
}
}
// do the ordering based on the rowOrder parameter
var orderList = order.split(",");
for(var k=0; k<orderList.length; k++){
for(var l=0; l<output.length; l++){
if(output[l].Row == orderList[k]){
request.push(output[l]);
break;
}
}
}
return request;
}
Outputs an array of objects in the order specified by the My_rowOrder parameter:
[
{
Row: "2",
Type: "Sony",
Value: "PS4",
Category: "Console"
},
{
Row: "1",
Type: "SSD",
Value: "16GB",
Category: "Disk Capacity"
}
]

This may works for you...
<script>
var data = "My_Type_2=Sony&My_Value_2=PS4&My_Category_2=Console";
var array = new Array();
alert(JSON.stringify(URLToArray(data)));
function URLToArray(url) {
var request = {};
var pairs = url.substring(url.indexOf('?') + 1).split('&');
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].split('=');
request[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
}
return request;
}
</script>

Try this:
function StringToArray(string) {
var request = [[],[]];
var pairs = string.split('&');
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].split('=');
request[pair[0].slice(-1)-1][decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
}
//console.log(request)
}

Related

How to clean , from a given string?

I have data like this.
var abc =",,,,,,,,,,,,,,,paul,2000,12sc21,logan,123,21sdf34,vfsarwe,456456,32fd23";
abc = abc.split(",");
let stub={};
var results=[];
var key=["name","value","acc"];
var i=0;
var j=0;
for( var i = 0 ; i <abc.length - 1;i++){
stub[key[j]=abc[i];
j++
if(j==3){
results.push(stub);
stub={};
j=0;
}
}
abc = results;
I would like to get those values arranges in form of array of object having those 3 keys:
output should be:
abc = [{"name": "paul", "value": "2000","acc":"12sc21"},{"name":"logan","value":"123","acc":"21sdf34"},{"name":"vfsarwe","value":"456456","acc":"32fd23"}];
but not able to get the desired output. this output only comes when string don't have ,,,,,, in starting. But the data i'm getting is sometimes having ,,,,, in stating.
You can use abc.replace(/(^[,\s]+)/g, '') to remove leading commas or whitespace from the String. Your for loop is also not running for long enough; it is looping until there is only one element left in the Array and then stopping.
Change
for(var i = 0 ; i < abc.length-1; i++)
To
for(var i = 0 ; i < abc.length; i++)
var abc =",,,,,,,,,,,,,,,paul,2000,12sc21,logan,123,21sdf34,vfsarwe,456456,32fd23";
abc = abc.replace(/(^[,\s]+)|([,\s]+$)/g, '').split(",");
let stub={};
var results=[];
var key=["name","value","acc"];
var i=0;
var j=0;
for(var i = 0 ; i < abc.length; i++){
stub[key[j]]=abc[i];
j++
if(j==3){
results.push(stub);
stub={};
j=0;
}
}
abc = results;
console.log(abc);
You can use .replace(/^\,+/, '') to remove all leading commas, then split by comma to get an array, then loop over this array using 3 as step and construct your results:
var abc = ",,,,,,,,,,,,,,,paul,2000,12sc21,logan,123,21sdf34,vfsarwe,456456,32fd23";
var arr = abc.replace(/^\,+/, '').split(",");
var results = [];
for (var i = 0; i < arr.length; i = i + 3) {
results.push({
"name": arr[i],
"value": arr[i + 1],
"acc": arr[i + 2]
});
}
Demo:
var abc = ",,,,,,,,,,,,,,,paul,2000,12sc21,logan,123,21sdf34,vfsarwe,456456,32fd23";
var arr = abc.replace(/^\,+/, '').split(",");
var results = [];
for (var i = 0; i < arr.length; i = i + 3) {
results.push({
"name": arr[i],
"value": arr[i + 1],
"acc": arr[i + 2]
});
}
console.log(results);
You are on the right track with splitting your data on ,. You can then split the data in to chunks of 3, and from there map each chunk to a dict.
var data = ",,,,,,,,,,,,,,,paul,2000,12sc21,logan,123,21sdf34,vfsarwe,456456,32fd23";
var split = data.split(",");
var chunked = [];
while (split.length) {
chunked.push(split.splice(0,3));
}
var res = chunked.map((i) => {
if (!i[0] || !i[1] || !i[2]) {
return null;
}
return {
name: i[0],
value: i[1],
acc: i[2]
};
}).filter((i) => i !== null);
console.log(res);
You can use:
abc.replace(/,+/g, ',').replace(/^,|,$/g, '').split(',');
The regEx replaces removes the data that you are not interested in before performing the split.
or
abc.split(',').filter(Boolean);
The filter(Boolean) will remove the items from the array that could be the equivalent of false once the array has been instantiated.
EDIT:
var abc =",,,,,,,,,,,,,,,paul,2,000,12sc21,logan,123,21sdf34,vfsarwe,456456,32fd23";
var array = abc.replace(/,+/g, ',').replace(/^,|,$/g, '').split(/,([0-9,]+),/);
array = array.filter(Boolean).reduce(function(acc, item) {
if (item.match(/^[0-9,]+$/)) {
acc.push(item);
} else {
acc = acc.concat(item.split(','));
}
return acc;
}, []);

Javascript. access property by string

I have a function that takes two lists(each item in the two lists are the same type). It only adds item from the second list to the first list if the item in the second list does not exist in the first list. To determine if it exist in the list, I compare the property pk.
addUniqueItemsToList: function (sourceList, toAddList) {
for (var a = 0; a < toAddList.length; a++) {
var doesItemExist = false;
for (var b = 0; b < sourceList.length; b++) {
if (sourceList[b].pk == toAddList[a].pk) {
doesItemExist = true;
break;
}
}
if (!doesItemExist) {
sourceList.push(toAddList[a]);
}
}
}
Is there a way in javascript where instead of comparing pk, I can compare it to other properties of the object, by passing in the name of the property to the function? i.e., addUniqueItemsToList: function (sourceList, toAddList, propertyName)
Yes you can compare by object property directly and access properties dinamically using string as key ej array['mykey']. Also it would be better if instead of doing a for inside a for (1for - n for) create a map in order to avoid so much iterations:
Eg: Number iterations without a map when items.length = 100 & anotherItems.length = 200
100*200 = 20000 possibles iterations.
Eg. Number of iterations creating a map with items.length = 100 & anotherItems.length = 200
300 iterations.
Example of how i do it:
var items = [{_id: 1, text: "Text 1"}, {_id:2, text: "Text 2"}];
var anotherItems = [{_id: 1, text: "Text 1"}];
var mapByProperty = function(array, prop) {
var map = [];
for (var i = 0, len = array.length; i !== len; i++) {
map[array[i][prop]] = array[i];
}
return map;
};
var commonUniqueProperty = '_id';
var mappedAnotherItemsById = mapByProperty(anotherItems, commonUniqueProperty);
for(var i = 0, len = items.length; i !== len; i++) {
if(mappedAnotherItemsById[items[i][commonUniqueProperty]]) {
console.log(items[i]);
}
}

Count how many strings in an array have duplicates in the same array [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Array value count javascript
I have an array which contains several duplicates, what I'm trying to achieve is to count how many duplicates each unique string has in this one array.
The array looks something like this
array = ['aa','bb','cc','aa','ss','aa','bb'];
Thus I would like to do something like this
if (xWordOccurrences >= 5) {
// do something
}
But I'm not sure how I would code this.
I was thinking, create an object with each unique string, then loop through the original array, match each string with it's object and increment it's number by 1, then loop over the object to see which words had the most duplicates...
But this seems like an over complexe way to do it.
You can use an object which has keys of the Array's values and do something like this
// count everything
function getCounts(arr) {
var i = arr.length, // var to loop over
obj = {}; // obj to store results
while (i) obj[arr[--i]] = (obj[arr[i]] || 0) + 1; // count occurrences
return obj;
}
// get specific from everything
function getCount(word, arr) {
return getCounts(arr)[word] || 0;
}
getCount('aa', ['aa','bb','cc','aa','ss','aa','bb']);
// 3
If you only ever want to get one, then it'd be more a bit more efficient to use a modified version of getCounts which looks similar to getCount, I'll call it getCount2
function getCount2(word, arr) {
var i = arr.length, // var to loop over
j = 0; // number of hits
while (i) if (arr[--i] === word) ++j; // count occurance
return j;
}
getCount2('aa', ['aa','bb','cc','aa','ss','aa','bb']);
// 3
Try this function:
var countOccurrences = function(arr,value){
var len = arr.length;
var occur = 0;
for(var i=0;i<len;i++){
if(arr[i]===value){
occur++;
}
}
return occur;
}
var count = countOccurrences(['aaa','bbb','ccc','bbb','ddd'],'bbb'); //2
If you want, you can also add this function to the Array prototype:
Array.prototype.countOccurrences = function(value){
var len = this.length;
var occur = 0;
for(var i=0;i<len;i++){
if(this[i]===value){
occur++;
}
}
return occur;
}
How about you build an object with named property?
var array = ['aa','bb','cc','aa','ss','aa','bb'];
var summary = {};
var item = '';
for ( i in array){
item = array[i];
if(summary[item]){
summary[item] += 1;
}
else{
summary[item] = 1;
}
}
console.log( summary );
summary will contain like this
{aa: 3, bb: 2, cc: 1, ss: 1}
which you could then iterate on and then sort them later on if needed.
finally to get your count, you could use this summary['aa']
<script type="text/javascript">
var array = ['aa','bb','cc','aa','ss','aa','bb'];
var myMap = {};
for(i = 0; i < array.length; i++) {
var count = myMap[array[i]];
if(count != null) {
count++;
} else {
count = 1;
}
myMap[array[i]] = count;
}
// at this point in the script, the map now contains each unique array item and a count of its entries
</script>
Hope this solves your problem
var array = ['aa','bb','cc','aa','ss','aa','bb'];
var dups = {};
for (var i = 0, l = array.length; i < l; i++ ) {
dups[array[i]] = [];
}
for (str in dups) {
for (var i = 0, l = array.length; i < l; i++ ) {
if (str === array[i]) {
dups[str].push(str);
}
}
}
for (str in dups) {
console.log(str + ' has ' + (dups[str].length - 1) + ' duplicate(s)');
}
This function may do everything you need.
function countDupStr(arr, specifier) {
var count = {}, total = 0;
arr.forEach(function (v) {
count[v] = (count[v] || 0) + 1;
});
if(typeof specifier !== 'undefined') {
return count[specifier] - 1;
}
Object.keys(count).forEach(function (k) {
total += count[k] - 1;
});
return total;
}
Each value in the array is assigned and incremented to the count object. Whether or not a specifier was passed, the function will return duplicates of that specific string or the total number of duplicates. Note that this particular technique will only work on string-coercible values inside your arrays, as Javascript can only index objects by string.
What this means is that during object assignment, the keys will normalize down to strings and cannot be relied upon for uniqueness. That is to say, this function wouldn't be able to discern the difference between duplicates of 3 and '3'. To give an example, if I were to perform:
var o = {}, t = {};
o[t] = 1;
console.log(o);
The key used in place of t would eventually be t.toString(), thus resulting in the perhaps surprising object of {'[object Object]': 1}. Just something to keep in mind when working with Javascript properties.
I saw this post about it, perhaps it can help:
http://ryanbosinger.com/blog/2011/javascript-count-duplicates-in-an-array/

Remove duplicate element pairs from multidimensional array

I have an array that looks like this:
1. coordinates = [ [16.343345, 35.123523],
2. [14.325423, 34.632723],
3. [15.231512, 35.426914],
4. [16.343345, 35.123523],
5. [15.231512, 32.426914] ]
The latitude on line 5 is the same as on line 3, but they have different longitudes and are therefore not duplicates.
Both the latitude and longitude are the same on line 3 and 6, and are therefore duplicates and one should be removed.
The difficulty in this question that different arrays never compare equal even if they contain same values. Therefore direct comparison methods, like indexOf won't work.
The following pattern might be useful to solve this. Write a function (or use a built-in one) that converts arrays to scalar values and checks if these values are unique in a set.
uniq = function(items, key) {
var set = {};
return items.filter(function(item) {
var k = key ? key.apply(item) : item;
return k in set ? false : set[k] = true;
})
}
where key is a "hash" function that convert items (whatever they are) to comparable scalar values. In your particular example, it seems to be enough just to apply Array.join to arrays:
uniqueCoords = uniq(coordinates, [].join)
You can use standard javascript function splice for this.
for(var i = 0; i < coordinates.length; i++) {
for(var j = i + 1; j < coordinates.length; ) {
if(coordinates[i][0] == coordinates[j][0] && coordinates[i][1] == coordinates[j][1])
// Found the same. Remove it.
coordinates.splice(j, 1);
else
// No match. Go ahead.
j++;
}
}
However, if you have thousands of points it will work slowly, than you need to consider to sort values at first, then remove duplicates in one loop.
I rewrote the answer from thg435 (It does not allow me to post comments) and prototype it also using jQuery instead, so this will work on all browsers using it (Even IE7)
Array.prototype.uniq = function (key) {
var set = {};
return $.grep(this, function (item) {
var k = key
? key.apply(item)
: item;
return k in set
? false
: set[k] = true;
});
}
You can use it like:
arr = arr.uniq([].join);
If you are not on Safari this single liner could do the job
var arr = [[16.343345, 35.123523],
[14.325423, 34.632723],
[15.231512, 35.426914],
[16.343345, 35.123523],
[15.231512, 32.426914]],
lut = {},
red = arr.filter(a => lut[a] ? false : lut[a] = true);
document.write("<pre>" + JSON.stringify(red,null,2) + "</pre>");
It might be simpler to create another array keeping only unique coordinate pairs
var uniqueCoors = [];
var doneCoors = [];
for(var x = 0; x < coordinates.length; x++) {
var coorStr = coordinates[x].toString();
if(doneCoors.indexOf(coorStr) != -1) {
// coordinate already exist, ignore
continue;
}
doneCoors.push(coorStr);
uniqueCoors.push(coordinates[x]);
}
function sortCoordinates(arr){
var obj = {};
for(var i = 0, l = arr.length; i < l; i++){
var el = arr[i];
var lat = el[0];
var lng = el[1];
if(!obj[lat + lng]){
obj[lat + lng] = [lat, lng];
}
}
var out = [];
for(p in obj){
out.push([obj[p][0], obj[p][1]]);
}
return out;
}
I am not sure about coordinates[][] dataType. Make the comparison accordingly.
var dubJRows= new Array();
for(int i = 0; i < coordinates.length -2; i++){
for(int j = i+1; j < coordinates.length -1; j++){
if (i != j && chk_dubJRows_not_contains(j)) {
innerArray1 [1][1] = coordinates[i];
innerArray2 [1][1] = coordinates[j];
if ( innerArray1 [1][0] == innerArray2[1][0]
&& innerArray1[1][1] == innerArray2[1][1]) {
dubJRows.push(j);
}
}
}
}
//REMOVE ALL dubJRows from coordinates.

Getting Inividual values from a Javascript Array

How can i get each variable into my javascript variable of a Javascript Array into my variable ??
I have this data
var Data = [
{open:100,high:104.06},
{open:103,high:105.06},
{open:107,high:106.06},
{open:109,high:107.06}
];
I have a function where i want to return each single value of this
For example
for(var i = 0; i<Data.length; i++)
var date = Data [i].open;
return date ;
Function can't return more than one value.
What you can do, is return new array with all the "open" values:
function GetDates() {
var dates = [];
for(var i = 0; i<Data.length; i++)
dates.push(Data[i].open);
return dates;
}
This way you can get the value of the second item (103) with such code:
var arrDates = GetDates();
alert(arrDates[1]);
Try with:
var Data = [
{open:100,high:104.06},
{open:103,high:105.06},
{open:107,high:106.06},
{open:109,high:107.06}
];
function getOpens(Data) {
var opens = [];
for(var i = 0; i<Data.length; i++) {
if ( opens.indexOf( Data[i].open ) == -1 ) {
opens.push( Data[i].open );
}
}
return opens;
}
var numbers = getOpens( Data ).join(' ');
It will returns an array with open properties.

Categories