Find elements from concatenate strings in JS - javascript

How can I search the values in an Object from strings, something like:
const query = "['arg1']['arg2']"
const renderImage = async (index) => {
const data = await fetchImage(index)
const image = document.querySelector('.div')
image.setAttribute("src", data`${query}`)
}
The fetch function is perfect working.
Edit:
The image source is in the data['arg1']['arg2']. If I use image.setAttribute("src", data['arg1']['arg2']) the code runs fine, but I need to do this dynamically and concatenate strings will help me.
Summing up: can I get the same result data['arg1']['arg2'] concatenating object and "query" (['arg1']['arg2'])?

you can store the path as an array of keys and access it like this
const query = ['arg1', 'arg2']
...
image.setAttribute("src", query.reduce((o, k)=>o[k], data))

It seems you are trying to extract the property names you want, from a poorly formatted string. Ideally, you would get query into a better format to begin with, so you don't have to parse the string. For instance, if you could get query as two separate variables:
const query1 = 'arg1';
const query2 = 'arg2';
image.setAttribute("src", data[query1][query2]);
you could also store query in a better data type to do this, like const query = { arg1: 'arg1', arg2: 'arg2' }; then access with dot syntax data[query.arg1][query.arg2].
But if you must keep query as this weirdly formatted string for some reason, you can do something like this, parsing the string into it's parts, putting them into an array, then using the array to access the right data within data.
let query = "['arg1']['arg2']";
query = query.slice( 2 ).slice( 0, -2 ).split( "']['" );
image.setAttribute( "src", data[query[0]][query[1]] );

Related

what are the ways to convert a simple array to 'nested array in javascript?

I want to capture screenshots on my remote virtual machine without using display. I came across a library in nodejs 'capture screenshot' (https://github.com/sindresorhus/capture-website) which is pretty straightforward.
Taking screenshot of a single link is fairly simple, however taking multiple screenshots becomes tricky. I don't want to put links manually as it will be time consuming. I am running a script to get all anchor tags in python and saving a csv file of links gathered. This is how it looks when I convert the saved csv file to a JavaScript array.
[ 'https://www.google.com/imghp?hl=en&tab=wi',
'https://maps.google.com/maps?hl=en&tab=wl',
'https://play.google.com/?hl=en&tab=w8',
'https://www.youtube.com/?gl=US&tab=w1',
'https://news.google.com/nwshp?hl=en&tab=wn',
'https://mail.google.com/mail/?tab=wm',
'https://drive.google.com/?tab=wo',
'https://www.google.com/intl/en/about/products?tab=wh',
'https://accounts.google.com/ServiceLogin?hl=en&passive=true&continue=https://www.google.com/',
'https://www.google.com/url?q=https://lifeinaday.youtube/%3Futm_source%3Dgoogle%26utm_medium%3Dhppcta%26utm_campaign%3D2020&source=hpp&id=19019062&ct=3&usg=AFQjCNEJMAD58Mjdnro8Mjm-RtJ3nfEIZA&sa=X&ved=0ahUKEwi98PWM4-HqAhVh1uAKHeYGCPwQ8IcBCAU'
]
I want to convert the above array to the array shown below.
[
['https://www.google.com/imghp?hl=en&tab=wi', 'anyanme'],
['https://maps.google.com/maps?hl=en&tab=wl','anyanme'],
['https://play.google.com/?hl=en&tab=w8','anyanme'],
['https://www.youtube.com/?gl=US&tab=w1','anyanme'],
['https://news.google.com/nwshp?hl=en&tab=wn','anyanme'],
['https://mail.google.com/mail/?tab=wm','anyanme'],
['https://drive.google.com/?tab=wo','anyanme'],
['https://www.google.com/intl/en/about/products?tab=wh','anyanme'],
['https://accounts.google.com/ServiceLogin?hl=en&passive=true&continue=https://www.google.com/','anyanme'],
['https://www.google.com/url?q=https://lifeinaday.youtube/%3Futm_source%3Dgoogle%26utm_medium%3Dhppcta%26utm_campaign%3D2020&source=hpp&id=19019062&ct=3&usg=AFQjCNEJMAD58Mjdnro8Mjm-RtJ3nfEIZA&sa=X&ved=0ahUKEwi98PWM4-HqAhVh1uAKHeYGCPwQ8IcBCAU','anyanme']
];
``
I am newbie to javscript and having a hard time to solve this. Any help will be appreciated.
It looks like the library you're using wants an array of pairs, with a URL and a file name.
I would map your original array to the array of pairs, but you'll have to figure out what you want to do for file names.
Assuming you have a function, named toFileName that will take a URL string and return a file name that you want for that URL, you could map the original array into the array of pairs like this:
const pairArr = originalArray.map((url) => {
const fileName = toFileName(url);
return [url, fileName];
});
If you just want to try to use the URL as the filename, you could just do this:
const pairArr = originalArray.map((url) => {
return [url, url];
});
This will be an issue with most URLs, though, as they'll have characters that are invalid for filenames. If you need a file extension with this approach, you could use string concatenation (url + '.png') for the second item in the returned pair.
You ca achieve it with a Map and regex
const arr = ['https://www.google.com/imghp?hl=en&tab=wi',
'https://maps.google.com/maps?hl=en&tab=wl',
'https://play.google.com/?hl=en&tab=w8',
'https://www.youtube.com/?gl=US&tab=w1',
'https://news.google.com/nwshp?hl=en&tab=wn',
'https://mail.google.com/mail/?tab=wm',
'https://drive.google.com/?tab=wo',
'https://www.google.com/intl/en/about/products?tab=wh',
'https://accounts.google.com/ServiceLogin?hl=en&passive=true&continue=https://www.google.com/',
'https://www.google.com/url?q=https://lifeinaday.youtube/%3Futm_source%3Dgoogle%26utm_medium%3Dhppcta%26utm_campaign%3D2020&source=hpp&id=19019062&ct=3&usg=AFQjCNEJMAD58Mjdnro8Mjm-RtJ3nfEIZA&sa=X&ved=0ahUKEwi98PWM4-HqAhVh1uAKHeYGCPwQ8IcBCAU',
'',
];
function extractName(str) {
const regex = /https:\/\/(.*?)\//g;
const ret = regex.exec(str);
return (ret && ret[1]) || null;
}
const items = arr.map(x => [
x,
extractName(x),
]);
console.log(items);

There is way to save only part of the string object into async-storage?

There is way to save only part of the string object into async-storage ?
for example if inside the "result.userPrincipalName" it save " bob23#hotmail.com "
so i want it will be save only the "bob23" , so what is the way to do it ?
await AsyncStorage.setItem(
'AZURE-USERNAME',
JSON.stringify(
result.userPrincipalName.substring(0, data.indexOf('#'))
)
);
You condo something like this.
You can remove part of the string after a certain character.
As I can see in the documentation. It stores as a key-value pair.
So I made changes
let data = JSON.stringify(result.userPrincipalName);
//here substring will remove characters after and including `#`
data = data.substring(0, data.indexOf('#'));
await AsyncStorage.setItem('AZURE-USERNAME', data);
I believe that you need to handle your desirable data on top level (add new input to user / new field in db with desired data etc. I don't know whereby you get your userPrincipalName).
But, if it's not possible, you can follow something like this:
const name = result.userPrincipalName.split('#')[0];
if (!name) throw new Error('Invalid email');
await AsyncStorage.setItem('AZURE-USERNAME', name);
Simply you can use split function in Javascript. More information
//Split the mame using split function
const splitName = result.userPrincipalName.split("#");
//Get the split value and save it
//After you splitting [0] mean first character set
const name = splitName[0];
//Save it to AsyncStorage
await AsyncStorage.setItem("AZURE-USERNAME", JSON.stringify(name));

Looking up value from CSV and return result

I'm attempting to use Javascript to lookup a value in a CSV file and return it's corresponding value (basically what a VLOOKUP does in Excel)
I've been able to follow some examples separately of pulling the CSV data into an array, and I've seen some examples of looking up data in arrays - but for the life of me I can't figure out how to get both working.
For example, the CSV file stations.csv has the following data:
mac,name
69167f276e9g,LINE1
69167f276e9f,LINE2
What I want to be able to do is lookup the 'mac' value from the CSV, and return the corresponding 'name' value.
So if I look for '69167f276e9f' I want to get the value LINE2 back.
[EDIT: Adding the code I've tried using MauriceNino's suggestion - but getting error Uncaught TypeError: Cannot read property '1' of undefined at the line 'return result[1];' ]:
$.ajax('stations.csv').done(function(data) {
const lookup = (arr, mac) => {
let twoDimArr = dataArr.map(el => el.split(',')); // map it to array of arrays of strings (data)
let result = twoDimArr.filter(el => el[0] == mac)[0]; // Get the first element where the mac matches the first element in the array
return result[1]; // Return the second element in the array
};
let dataArr = data.split('\n');
dataArr .shift(); // Remove the first array element (The header)
let resultMac = lookup(dataArr, "69167f276e9f");
console.log(resultMac);
})
Here is a possible solution:
It first creates a two-dimensional array from your data
Then it searches the first element that has the specified mac as the first value
Then it returns the second element of that array
const data = `mac,name
69167f276e9g,LINE1
69167f276e9f,LINE2`;
const lookup = (arr, mac) => {
let twoDimArr = dataArr.map(el => el.split(',')); // map it to array of arrays of strings (data)
let result = twoDimArr.filter(el => el[0] == mac)[0]; // Get the first element where the mac matches the first element in the array
return result[1]; // Return the second element in the array
}
let dataArr = data.split('\n');
dataArr .shift(); // Remove the first array element (The header)
let resultMac = lookup(dataArr, '69167f276e9f');
console.log(resultMac);
I just finished writing a script doing almost the exact same thing.
What I did there is I streamed the csv file using the readline and fs libraries:
csvStream = readline.createInterface({
input: fs.createReadStream(filePath);
});
Then, I manually parsed each line of the csv using the line event of the readline stream library:
decompressedStream.on('line', (line) =>
My csv has kind of a special structure, so I had to do manual parsing and some modifications to values, but basically the idea is splitting the string you get as 'line' using line.split and your delimeter, and then push each value to a cell in the array.
what you get is an array that each cell in it represents one value in the csv line, and then you can push it to another big array which represents the whole csv and each cell in it represents a line.
after that, you can use the close event to know when the stream ended:
decompressedStream.on('close', () =>
and then its just a matter of using array.find the whole csv array to find the value you looking for:
let res = csvArray.find(val => val[0] == curMac)
and then
return res[1]
EDIT: i just saw MauriceNino's answer, which is very similar to mine.
notice the differences:
in his answer he splits only using the delimeter, wheres in my case you have option to add more calculation or modifications to data before pushing it to the array for each line, and also account for special cases like when you have the delimeter inside a value surrounded by "". thats why I needed to use the stream method.
His method is perfect for small files, but loading extremely large files directly to memory can be bad. I was working on 15GB csv files, so I had to use the stream. This way I could load a few line, process them and dump my data, and then again load a bulk of lines.
As it seems, his logic is better suited for your case, but I do not know the whole flow or purpose of your program, so I will leave my answer here for you to decide which is better suited for you :)
First convert the CSV to an Array of objects.
Than use Array.prototype.find() to find in that Array the Object which property value matches a desired string.
const csv2array = (csv, dlm = ',') => {
const [heads, ...lines] = csv.split('\n'), th = heads.split(dlm);
return lines.map(l => l.split(dlm).reduce((o, c, i) => (o[th[i]] = c.trim(), o), {}));
}
const findInCSV = (csv, p, v) => csv2array(csv).find(k => k[p] === v);
// Getting stuff:
const myCSV = `mac,name
69167f276e9g,LINE1
69167f276e9f,LINE2`;
console.log(findInCSV(myCSV, 'mac', '69167f276e9g')) // Get entire object by knowing the mac
console.log(findInCSV(myCSV, 'mac', '69167f276e9g').name) // Get name knowing the mac
console.log(findInCSV(myCSV, 'name', 'LINE1')) // Get entire object by knowing the name
console.log(findInCSV(myCSV, 'name', 'LINE1').mac) // Get mac knowing the name
Sounds like you need a dictionary, for example:
var myMappings = {
'69167f276e9f': 'LINE1',
'69167f276e9g': 'LINE2'
};
var myVal = myMappings['69167f276e9g'];
alert(myVal); // prints LINE2

Split string using regex expression

I need to split a dynamic string. The string may look like the one below having Code, Name and EffectDate. or it may have only (Code and Name) or (Code and EffectDate) or (Name and EffectDate). You got the point right.
{"Code":{"value":"1"},"Name":{"value":"Entity1"},"EffectDate":{"value":"23/11/2016"}}
to
...
this.data[0].key ='Code'; \\something like this (desired result)
this.data[0].value = '1';
this.data[1].key = 'Name';
this.data[1].value = 'Entity1';
this.data[2].key = 'EffectDate';
this.data[2].value = '23/11/2016';
What i did in my code :
...
filters:string;
data:string[];
...
this.data = this.filters.split("\b(?:(?!value)\w)+[a-zA-Z0-9/]\b");
console.log(this.data);
I used this pattern \b(?:(?!value)\w)+[a-zA-Z0-9/]\b but still couldn't get the desired result. The this.filter always returns only one array with the same string. Any advice would be helpful. Thank you.
Update #1:
I'm using PrimeNg extension for datatable and i get event as a parameter. In that, event.filters returns me a list of filter objects. I cannot send the object to the service, it needs to be in the format to work with the service.
That looks like JSON. What's to stop you from just doing data = JSON.parse(content) and iterating over the key-values using keys(data) for keys and data[i]["value"] for values?
Try something like this:
var data = [];
for(var i in event.filters){
data.push({"key": i, "value": event.filters[i].value});
}

Escaping JSON to avoid changing the insert string

I have the following json string that should be inserted directly into the database in a single column:
const jsString = JSON.stringify({"escaping":"d\"on't"});
const insertion = [{"a":2,"json":jsString}];
const query = pgp.helpers.insert(insertion,["a","json"],"tbl");
however what actually ends up in the database is:
{"escaping":"d"on't"}
removing the escaping \ in d"on't and making the string invalid json. Is there some way to avoid this?
This would be beneficial since it would be nice if my valid json would remain so.
Don't stringify your data into JSON, use it directly
Set column formatting as JSON, using :json modifier
const data = {escaping: "d\"on't"};
const insertion = [{a:2, json:data}];
const query = pgp.helpers.insert(insertion, ["a", "json:json"], "tbl");
But if your data is always an object, then you don't even need to use the :json modifier, it will be automatically formatted as correct JSON.
For more details see the flexibility of the ColumnSet type. You can manipulate your input data in every thinkable way.
This string in js const jsString = JSON.stringify({"escaping":"d\\\"on't"}); will result in this {"escaping":"d\\\"on't"}
While this string in js const jsString = JSON.stringify({"escaping":"don't"}); will result in this {"escaping":"don't"}

Categories

Resources