Javascript : Select Element in URL with multiple instance of the same element - javascript

i need to retrieve a value from an URL in JS, my problem is in this url, the element is repeated at least twice with different value. What i need is the last one.
Example :
http://randomsite.com/index.php?element1=random1&element2=random2&element1=random3
and what i want is "random3" and NOT "random1"
I've tried url.match(/.(\&|\?)element1=(.?)\&/)[2];
But it always gives me the first one :(
I don't have the possibility to change how the url is written as this is for a browser extension.

var ws = "http://randomsite.com/index.php?element1=random1&element2=random2&element1=random3",
input = ws.split("?")[1].split("&"),
dataset = {},
val_to_find = "element1";
for ( var item in input){
var d = input[item].split("=");
if (!dataset[d[0]]){ dataset[d[0]] = new Array(); dataset[d[0]].push(d[1]); }
else{
dataset[d[0]].push(d[1]);
}
}
console.log("item: ", dataset[val_to_find][dataset[val_to_find].length -1]);
return dataset[val_to_find][dataset[val_to_find].length -1];
http://jsfiddle.net/wMuHW/

Take the minimum value (other than -1) from urlString.lastIndexOf("&element1=") and urlString.lastIndexOf("?element1="), then use urlString.substring.
Or alternately, split the string up:
var parts = urlString.split(/[?&]/);
...which will give you:
[
"http://randomsite.com/index.php",
"element1=random1",
"element2=random2",
"element1=random3"
]
...then start looping from the end of the array finding the first entry that starts with element= and grabbing the bit after the = (again with substring).

You could;
for (var result, match, re = /[&?]element1=(.+?)(\&|$)/g; match = re.exec(url);) {
result = match[1];
}
alert(result);

Id try keeping a nested array of duplicate elements
function parseQueryString() {
var elements = {},
query = window.location.search.substring(1),
vars = query.split('&');
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split('='),
key = decodeURIComponent(pair[0]),
value = decodeURIComponent(pair[1]);
if (elements.hasOwnProperty(key)) {
elements[key].push(value);
}
else {
elements[key] = [value];
}
}
}
Used on: www.example.com?element1=hello&element2=test&element1=more
Would give you the object:
{
element1: [
"hello",
"more"
],
element2:[
"test"
]
}

Related

Output several cells from inner loop

this is my code:
start() {
let columns = ['A'...'Z'];
let fields = {
id: [
'Medlemsnummer',
],
name: [
'Namn',
],
};
let out = {};
let self = this;
columns.forEach(function(column) {
for(let row = 1; row < 101; row++) {
let cell = column + row;
let d_cell = self.worksheet[cell];
let val_cell = (d_cell ? d_cell.v : ' ');
let cell_string = val_cell.toString().toLowerCase();
let cellString_stripped = cell_string.replace(/(?:\r\n|\r|\n)/g, '');
for (var key in fields) {
// skip loop if the property is from prototype
if (!fields.hasOwnProperty(key)) continue;
var obj = fields[key];
for (var prop in obj) {
// skip loop if the property is from prototype
if(!obj.hasOwnProperty(prop)) continue;
obj.forEach(function(term) {
if(cellString_stripped.match(new RegExp(term.toLowerCase() + ".*"))){
//out.push(obj + ': ' + cell);
//out[obj] = {cell};
out[obj] = cell;
}
});
//out[obj]
}
}
}
});
console.log(out);
},
and my problem is that i want several matched cells in out[obj] = // array of matched cells.
how can i do this in javascript?
so my out should look like this:
out = [ medlemsnummer: ['A11','A23','A45'], name: ['B11','B23'] etc... ]
please comment if you need me to explain better.
Kind regards,
Joakim
Looking at your loops, I think you got a little lost in your own structures. out[obj] = cell definitely doesn't seem right; obj is an object, it cannot be used as a key in another object. Here's my take with some notes, hope I interpreted both your code and your question correctly. I'm starting from the loop after all your variables like cell, d_cell, etc. are initialized):
for (let key in fields) {
if (!fields.hasOwnProperty(key)) continue;
let terms = fields[key];
// fields[key] yields us an array, e.g.:
// fields['id'] = [ 'Medlemnummer' ]
// so we can iterate over it directly with for..of.
// Note also: variable names like "obj" make reading your code
// difficult; use meaningful names, e.g. "terms".
for (let term of terms) {
let regex = new RegExp(term.toLowerCase() + ".*");
// Note: RegEx.test() is more efficient than String.match()
// if all you need is a yes/no answer.
if (!regex.test(cellString_stripped)) continue;
// Here's the part you actually needed help with:
if (!out[term]) {
out[term] = [];
}
out[term].push(cell);
}
}
Addendum: In the code I'm sticking with your solution to use RegExp to test the strings. However, if all you need to check is whether the string starts with the given substring, then it's much shorter and more efficient to use String.startsWith():
for (let term of terms) {
if (!cellString_stripped.startsWith(term.toLowerCase())) continue;
// Here's the part you actually needed help with:
if (!out[term]) {
out[term] = [];
}
out[term].push(cell);
}

JavaScript Search and Loop - doesn't return correct values

Please, can you check my code where is the error? It should loop trough 1 array to choose each string and then loop through second array and check, if the value from second string contains value of first string.
for (var i = 0; i < oldLines.length; i++){
var subStringEach = oldLines[i];
var subStringEachNoDash = subStringEach.replace(/[^a-z0-9]/g,'');
// read New URLs and line by line save them as an object
var newLines = $('#newUrl').val().split(/\n/);
var newUrlResult = [];
for (var j = 0; j < newLines.length; j++){
var newUrlString = newLines[j];
var newUrlStringNoDash = newUrlString.replace(/[^a-z0-9]/g,'');
var isThere = newUrlStringNoDash.search(subStringEachNoDash);
if (isThere !== -1 ) {
newUrlResult[i] = newLines[j];
}
else {
newUrlResult[i] = "";
}
}
stockData.push({OldURL:oldLines[i],SearchSubstring:subStringEach,NewURL:newUrlResult[i]});
}
Now it finds only part of the results.. I place to first array:
anica-apartment
casa-calamari-real
ostrovni-apartman
and to the second array:
http://tempweb3.datastack.cz/be-property/anica-apartment/
http://tempweb3.datastack.cz/be-property/ostrovni-apartman/
http://tempweb3.datastack.cz/be-property/st-michael-apartment/
http://tempweb3.datastack.cz/be-property/casa-calamari-real/
and it will only find and return casa-calamari-real, http://tempweb3.datastack.cz/be-property/casa-calamari-real/ and the others returns empty..
Any ideas please?
Here is the full code on Codepen: https://codepen.io/vlastapolach/pen/VWRRXX
Once you find a match you should exit the inner loop, otherwise the next iteration of that loop will clear again what you had matched.
Secondly, you should use push instead of accessing an index, as you don't know how many results you will have. And as a consequence you will need to relate the find string with it (because i will not be necessary the same in both arrays)
So replace:
if (isThere !== -1 ) {
newUrlResult[i] = newLines[j];
}
else {
newUrlResult[i] = "";
}
with this:
if (isThere !== -1 ) {
newUrlResult.push({
searchSubstring: subStringEach,
newURL: newUrlString
});
break; // exit loop
}
At the end, just output newUrlResult.
NB: If you want to leave the possibility that a search string matches with more than one URL, then you don't need the break. The push will then still prevent you from overwriting a previous result.
I see that you solved already) But maybe you will like this code too)
newUrlResult variable could be a string I guess, because loop breaks when one value is found. If no values where found there will be just empty string. And I'm not sure you need to call newLines = $('#newUrl').val().split(/\n/) on every iteration.
var stockData = [];
oldLines.map(function(oldLine){
var cleanOldLine = oldLine.replace(/[^a-z0-9]/g,''),
newLines = $('#newUrl').val().split(/\n/),
newUrlResult = '';
for (var j = 0; j < newLines.length; j++){
var newLine = newLines[j],
cleanNewLine = newLine.replace(/[^a-z0-9]/g,''),
ifExists = cleanNewLine.search(cleanOldLine);
if (ifExists !== -1) {
newUrlResult = newLine;
break;
}
}
stockData.push({OldURL:oldLine, SearchSubstring:cleanOldLine, NewURL:newUrlResult});
});

Loop, get unique values and update

I am doing the below to get certain nodes from a treeview followed by getting text from those nodes, filtering text to remove unique and then appending custom image to the duplicate nodes.
For this I am having to loop 4 times. Is there is a simpler way of doing this? I am worried about it's performance for large amount of data.
//Append duplicate item nodes with custom icon
function addRemoveForDuplicateItems() {
var treeView = $('#MyTree').data('t-TreeView li.t-item');
var myNodes = $("span.my-node", treeView);
var myNames = [];
$(myNodes).each(function () {
myNames.push($(this).text());
});
var duplicateItems = getDuplicateItems(myNames);
$(myNodes).each(function () {
if (duplicateItems.indexOf($(this).text()) > -1) {
$(this).parent().append(("<span class='remove'></span>"));
}
});
}
//Get all duplicate items removing unique ones
//Input [1,2,3,3,2,2,4,5,6,7,7,7,7] output [2,3,3,2,2,7,7,7,7]
function getDuplicateItems(myNames) {
var duplicateItems = [], itemOccurance = {};
for (var i = 0; i < myNames.length; i++) {
var dept = myNames[i];
itemOccurance[dept] = itemOccurance[dept] >= 1 ? itemOccurance[dept] + 1 : 1;
}
for (var item in itemOccurance) {
if (itemOccurance[item] > 1)
duplicateItems.push(item);
}
return duplicateItems;
}
If I understand correctly, the whole point here is simply to mark duplicates, right? You ought to be able to do this in two simpler passes:
var seen = {};
var SEEN_ONCE = 1;
var SEEN_DUPE = 2;
// First pass, build object
myNodes.each(function () {
var name = $(this).text();
var seen = seen[name];
seen[name] = seen ? SEEN_DUPE : SEEN_ONCE;
});
// Second pass, append node
myNodes.each(function () {
var name = $(this).text();
if (seen[name] === SEEN_DUPE) {
$(this).parent().append("<span class='remove'></span>");
}
});
If you're actually concerned about performance, note that iterating over DOM elements is much more of a performance concern than iterating over an in-memory array. The $(myNodes).each(...) calls are likely significantly more expensive than iteration over a comparable array of the same length. You can gain some efficiencies from this, by running the second pass over an array and only accessing DOM nodes as necessary:
var names = [];
var seen = {};
var SEEN_ONCE = 1;
var SEEN_DUPE = 2;
// First pass, build object
myNodes.each(function () {
var name = $(this).text();
var seen = seen[name];
names.push(name);
seen[name] = seen ? SEEN_DUPE : SEEN_ONCE;
});
// Second pass, append node only for dupes
names.forEach(function(name, index) {
if (seen[name] === SEEN_DUPE) {
myNodes.eq(index).parent()
.append("<span class='remove'></span>");
}
});
The approach of this code is to go through the list, using the property name to indicate whether the value is in the array. After execution, itemOccurance will have a list of all the names, no duplicates.
var i, dept, itemOccurance = {};
for (i = 0; i < myNames.length; i++) {
dept = myNames[i];
if (typeof itemOccurance[dept] == undefined) {
itemOccurance[dept] = true;
}
}
If you must keep getDuplicateItems() as a separate, generic function, then the first loop (from myNodes to myNames) and last loop (iterate myNodes again to add the span) would be unavoidable. But I am curious. According to your code, duplicateItems can just be a set! This would help simplify the 2 loops inside getDuplicateItems(). #user2182349's answer just needs one modification: add a return, e.g. return Object.keys(itemOccurance).
If you're only concerned with ascertaining duplication and not particularly concerned about the exact number of occurrences then you could consider refactoring your getDuplicateItems() function like so:
function getDuplicateItems(myNames) {
var duplicateItems = [], clonedArray = myNames.concat(), i, dept;
for(i=0;i<clonedArray.length;i+=1){
dept = clonedArray[i];
if(clonedArray.indexOf(dept) !== clonedArray.lastIndexOf(dept)){
if(duplicateItems.indexOf(dept) === -1){
duplicateItems.push(dept);
}
/* Remove duplicate found by lastIndexOf, since we've already established that it's a duplicate */
clonedArray.splice(clonedArray.lastIndexOf(dept), 1);
}
}
return duplicateItems;
}

How to check an input words against several arrays in Javascript

I need to test all the words entered into an input against 3 objects and determine which array they belong to so I can output a URL to an API.
I want to achieve this with Javascript/jQuery.
For example if the input had these words: keyword1 keyword2 keyword3 keyword5
All keyword entries will be added from a autocomplete plugin.
I then need to test them against 3 arrays.
var array1 = ["keyword2", "keyword6"];
var array2 = ["keyword3", "keyword4"];
var array3 = ["keyword1", "keyword5"];
I need to determine what array they came from so I can output a URL and add the values to specific keys in a URL.
Example:
domain.com/api?array1= [insert keyword(s)] &array2= [insert keyword(s)] &array3= [insert keyword(s)]
The keywords need to be sent as an array and must have spaces replaced with dashes.
I am using jQuery to perform a GET request with the URL generated.
You can make the code shorter by creating an array of arrays but this works
var input = "keyword1 keyword2 keyword3 keyword5".split(" ");
var array1 = ["keyword2", "keyword6"];
var array2 = ["keyword3", "keyword4"];
var array3 = ["keyword1", "keyword5"];
var arr1=[],arr2=[],arr3=[];
$.each(input,function(_,keyword) {
if ($.inArray(keyword,array1) !=-1) arr1.push(keyword);
if ($.inArray(keyword,array2) !=-1) arr2.push(keyword);
if ($.inArray(keyword,array3) !=-1) arr3.push(keyword);
});
var url = "domain.com/api/?",keywords="";
if (arr1.length>0) keywords += "&array1="+arr1.join(",");
if (arr2.length>0) keywords += "&array2="+arr2.join(",");
if (arr3.length>0) keywords += "&array3="+arr3.join(",");
if (keywords.length>0) url += keywords.substring(1).replace(/ /g,"-");
console.log(url)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
You can put all the array objects into a parent array and then loop it
var parentArray = [
["keyword2", "keyword6"],
["keyword3", "keyword4"],
["keyword1", "keyword5"]
]
$.each(parentArray,function(key,value){
//here you can check
$.each(value,function(key1,value1){
if('your key word') == value1{
// then the array you are looking for would be "key" of that particular loop
}
});
});
EDIT: Now, this should definitely work
Here's a vanilla JS version:
var words = 'keyword1 keyword2 keyword3 keyword5';
// first create an object that contains your arrays
var dict = {
array1: ["keyword2", "keyword6"],
array2: ["keyword3", "keyword4"],
array3: ["keyword1", "keyword5"]
}
// start building up a new object that mirrors the existing one
// but that only contains those keywords that are in the input string
function buildURLObj(dict, words) {
var out = {};
// split the keywords string into an array
words = words.split(' ');
// loop over the object
for (var p in dict) {
out[p] = [];
// loop over the array of keywords
for (var i = 0, l = words.length; i < l; i++) {
// if the keyword in the array, push it to the
// temporary object
if (dict[p].indexOf(words[i]) > -1) {
out[p].push(words[i]);
}
}
}
// return the completed URL using createURL
return createURL(out);
}
// create a URL from the new object
function createURL(arr) {
var url = [];
for (var p in arr) {
// if the array is not empty, don't add it to the completed URL
// otherwise start building up the URL string
if [arr[p].length) {
var subURL = [];
subURL.push(p);
subURL.push('[' + arr[p].join('-') + ']');
url.push(subURL.join('='));
}
}
// return the completed URL
return url.join('&');
}
// "array1=[keyword2]&array2=[keyword3]&array3=[keyword1-keyword5]"
buildURL(dict, words);
DEMO

Get value from json object without count the array number

This is my json object i want to get alert it without the array order like[0], [1].
var jsononj = {
"objnew" :
[{testarry: "thi is my demo text" },
{testarry2: "thi is my demo text2" }
] };
}
var newtest = jsononj.objnew[0].testarry;
alert(newtest);
i want to alert without [0]. how to i achieve this
I think this is what you're looking for:
var i;
for (i = 0; i < jsonobj.objnew.length; i++) {
if (jsonobj.objnew[i].testarry) {
alert(jsonobj.objnew[i].testarry);
}
}
This is just stupid but I removed the [0]
var jsononj = {
"objnew" : [
{testarry: "thi is my demo text" },
{testarry2: "thi is my demo text2" }
]
};
var a = jsononj.objnew.shift();
alert(a.testarry);
jsononj.objnew.unshift(a);
That's not JSON, that's a Javascript object. JSON is a text format for representing data.
If you want to look for an object with a specific property, loop through the objects in the array and check for it:
var newtest = null;
for (var i = 0; i < jsononj.objnew.length; i++) {
var obj = jsononj.objnew[i];
if (obj.hasOwnProperty('testarry') {
newtest = obj.testarry;
break;
}
}
if (newtest != null) {
// found one
}
doing a var firstOne = jsononj.objnew[0];
but if you simply don't like the [0] through your lines, extend the Array prototype
Array.prototype.first = function () {
return this[0];
};
var newtest = jsononj.objnew.first().testarry;
alert(newtest);
more info at First element in array - jQuery

Categories

Resources