Javascript searching made easy - javascript

See Katana314's answer below
After spending days to figure out how to use regex for BBcode translation I have decided to reinvent the wheel and here I am.
I wrote a script that search for BBcode tags like [b][/b] or any other [] in the text.
I'm looking for an easy solution to compare the tags I found in the text and match them with a table, "array" if you prefer. I want to do it like that because eventually I will use a database to insert and remove BBcodes.
I kinda like the way I do the replacement cause its easy to populate. and there is no need for a Regex.
The replace fonction with it's array:
function bbToHtml(s) {
var p, pairs = [
{ "in": "[b]", "out": '<span style="color:red;">' },
{ "in": "[/b]", "out": '</span>' },
];
for (p in pairs) {
s = s.replace(pairs[p]["in"], pairs[p]["out"]);
}
return s;
}
Now that's fairly simple. What i would like to do is to compare my BBcode with the "in" values.
Lets say i have var BBCode = "[we]";
How do i proceed to see if it matchs one of my array value;
If the result is true then i can just do bbToHtml(BBCode); and if not i skip it or trow an error.

I love ES5 array functions.
function isBB(str) {
return !pairs.every(function(s) {
return s.in !== str;
});
}
every means "return true if this function returns true for all values of this array." This is assuming you are only looking for "[b]" and not "[b] " or any slight variation.

possible solution to your question:
var pairs = [
{ "in": "[b]", "out": '<span style="color:red;">' },
{ "in": "[/b]", "out": '</span>' },
];
function bbToHtml(s)
{
for (var p in pairs) {
s = s.replace(pairs[p]["in"], pairs[p]["out"]);
}
return s;
}
var search = '[we]';
if (pairs[search]) bbToHtml(search);

Related

split csv where fields contain commas

Thanks to the answer posted here: Put data from a csv file into an array (Javascript) I have been able to split a csv file in the manner I need to but I have come across a problem with the output. Nothing to do with the code as it works just as I wanted it to. The issue relates to the source data.
The csv files are provided to me as is so I did not realise that they had fields that contained commas. This means the split doesn't work as needed.
This is the code I am using:
$.get("export.csv", function process(dataString) {
var lines = dataString
.split(/\n/)
.map(function(lineStr) {
return lineStr.split(",");
});
var keys = lines[0];
var objects = lines
.slice(1)
.map(function(arr) {
return arr.reduce(function(obj, val, i) {
obj[keys[i]] = val;
return obj;
}, {});
});
console.log(objects);
})
This gives me the output in this format:
{
"PROBLEM_NUMBER": "ticket_number",
"CALLER_NAME": "\"surname",
"PRIORITY": " forename\"",
"CALL_TIME": "4",
"CALL_DETAILS": "date",
"RESOLVER": "group",
"RESTORING_GROUP": "\"surname",
"RESOLVING_GROUP": " forename\"",
"RESTORATION_TIME": "group",
"RAG_STATUS": "group",
"CALL_STATUS": "date",
"CALL_TYPE": "RED",
"RESTORATION_CODE": "Closed",
"SUBMITTER_GROUP": "Problem",
"ASSIGNEE_GROUP": "resolution",
"ASSIGNEE_NAME": "group",
"RESOLVED_DATE_TIME": "group",
"RESTORED_DATE_TIME": "",
"TIME_WITH_TEAM": "date",
"MONTH/YEAR\r": "date",
"undefined": "Jan-21\r"
}
As you can see, the final field is "undefined" due to 2 fields containing a comma and splitting incorrectly.
I know I need to use regex to modify the split correctly however I don't understand or know where to put it. Is anyone able to assist me please?
Thanks
I managed to solve the problem so thought I would post here for anyone else that may come across a similar issue:
To resolve it I declared the regex string as a variable and then called that in the .split() instruction.
The regex string I used was - /("[^"]+"|[^,]+)*,/g
My code now looks like this:
$.get("export.csv", function process(dataString) {
var regex = /("[^"]+"|[^,]+)*,/g;
var lines = dataString
.split(/\n/)
.map(function(lineStr) {
return lineStr.split(regex);
});
var keys = lines[0];
var objects = lines
.slice(1)
.map(function(arr) {
return arr.reduce(function(obj, val, i) {
obj[keys[i]] = val;
return obj;
}, {});
});
console.log(objects);
})
This gives me the correct output I need and maps all values accordingly

Functions Invoking other Functions exercise I'm stumped on

First-time poster here and have run into a speed bump in my pre-work for a 6-month full-stack boot camp I'm enrolled in for November.
I'm working on some exercises on repl.it and this one is on javascript functions. You're told to write 3 functions called mealMaker, slice, and cook.
You're given an empty array and are told to fill it with objects like so:
const arrayOfFoodObjects = [
{
"food": "beef",
"type": "meat"
},
{
"food": "zucchini",
"type": "vegetable"
},
{
"food": "bacon",
"type": "meat"
},
{
"food": "okra",
"type": "vegetable"
}
];
They want you to have the cook function take all the objects that have "type": "meat" and return a string that says "Cooked ("food": value)" (e.g. "Cooked beef") and similarly with the slice function for "type": "vegetable" they want "("food": value) slices" (e.g. "Okra slices").
Then the mealMaker function takes what those functions spit out and creates an array as such: ["Cooked beef", "Okra slices" ...].
Where I'm stuck is I wrote a .filter() function that just returns a filtered array of those objects which I soon realized wouldn't serve its purpose. I guess I'm trying to figure out how to write a function so I can filter the meat and vegetables separately and then have them spit out the required string.
What's confusing me is how to target the "food" value and plug it into a certain string after filtering with the "type" value.
This is the rest of the code I have written so far which may or may not help.
var redMeat = arrayOfFoodObjects.filter(function(cook) {
return cook.type == "meat";
});
var veggies = arrayOfFoodObjects.filter(function(slice) {
return slice.type == "vegetable";
});
console.log(veggies, redMeat)
With the console just looking like:
[ { food: 'zucchini', type: 'vegetable' },
{ food: 'okra', type: 'vegetable' } ] [ { food: 'beef', type: 'meat' },
{ food: 'bacon', type: 'meat' } ]
I'm probably not tackling this the right way as I've spent a good amount of time trying different things I had found on Google and applying them as best I could but this was the closest I managed to get. Any help is greatly appreciated, thanks.
PS I'm not super familiar with this format of a function as I came up with this through some searches on Google. If someone wouldn't mind explaining how this may differ from the function format I'm used to seeing, that'd be awesome. I'm not sure about which part of it is the "name" of the function. The functions I've worked with so far typically look like:
function nameOfFunction(value(s)) {
*action*;
}
You are not doing what they ask.
They want a cook function and a slice function:
function cook(arr){
//for each element of the array, return its mapped value (they ask a string)
return arr.map( function(foodObject){
return `Cooked ${foodObject.food}`
})
}
function slice(arr){
//do it
}
let cooks = cook(arrayOfFoodObjects)
let slices = slice(arrayOfFoodObjects)
then feed what the function spit out to mealMaker (as instructed):
function mealMaker(cooks, slices){
return cooks.map( function(cook, idxCook){
let slice = slices[idxCook];
//guess what to do with cook and slice
})
}
mealMaker(cooks, slices)
I think something alone these lines is requested:
const cook = product => "cooked " + product.food;
const slice = product => product.food + " slices";
const mealMaker = (products) => {
const meatProducts = products.filter(product => product.type === "meat");
const veggieProducts = products.filter(product => product.type === "vegetable");
return [
...cook(meatProducts),
...slice(veggieProducts)
];
}
mealMaker(arrayOfFoodObjects);
Notice the fat arrow syntax for writing functions. How it is different compared to regular functions, is explained here on Mozilla.
Welcome holdenprkr!
I think you are on the right track! For now, we have a way to get an array of veggies and another one for meats:
var redMeat = arrayOfFoodObjects.filter(function(cook) {
return cook.type == "meat";
});
var veggies = arrayOfFoodObjects.filter(function(slice) {
return slice.type == "vegetable";
});
So far so good, now we want a cook function that takes our readMeat array, and converts it to a array of strings. So, something in the lines of:
function cook(readMeatsArray) {
// convert readMeatsArray to cookedMeatsArray
// [{'food': 'beef', 'type': 'meat'}, ...]
// to
// ['Cooked beef', ...]
}
And then a slice function for the veggies:
function slice(veggiesArray) {
// convert veggiesArray to slicedVeggiesArray
// [{'food': 'okra', 'type': 'vegetable'}, ...]
// to
// ['Okra slices', ...]
}
So, if we combine this in an mealMaker function we now have:
function mealMaker() {
// First we get our arrays
var redMeat = arrayOfFoodObjects.filter(function(cook) {
return cook.type == "meat";
});
var veggies = arrayOfFoodObjects.filter(function(slice) {
return slice.type == "vegetable";
});
// Then we convert our object arrays to string arrays
var cookedMeats = cook(redMeat);
var slicedVeggies = slice(veggies);
// Now we combine the resulting arrays and return it
var mealArray = cookedMeats.concat(slicedVeggies);
return mealArray;
}
This would be one approach, hope it helps.
PD: I left the functions cook and slice empty on purpose, you can get some inspiration from user753642's answer ;)

Validating list of email extention set as JSON in JavaScript

How can I validate user inputted email and check their extension with a list of email extensions in a JSON?
Like if I type abc#efg.com its going to check only the email extension which is #efg.com in a list of JSON.
OR a regex that will only get the values after "#" and ignore anything before that.
[
{
"School": "Ivy Tech Community College",
"Email": "ivytech.edu"
},
{
"School": "Liberty University",
"Email": "liberty.edu"
},
{
"School": "Miami Dade College",
"Email": "mdc.edu"
},
{
"School": "Lone Star College",
"Email": "lonestar.edu"
},
{
"School": "Ashford University",
"Email": "ashford.edu"
}
]
// initial data
var data = '[ {"School":"Ivy Tech Community College","Email":"ivytech.edu"},' + '{"School":"Liberty University","Email":"liberty.edu"},' + '{"School":"Miami Dade College","Email":"mdc.edu"},' + '{"School":"Lone Star College","Email":"lonestar.edu"},' + '{"School":"Ashford University","Email":"ashford.edu"} ]';
// json-ify our data
var jsonData = JSON.parse(data);
// map the values of each JSON 'Email' property from jsonData in an array
var emailsArray = jsonData.map(function (x) { return x.Email; });
// email address for testing
var testEmail = "john#liberty.edu";
// split the email address by the "#" character and use the second part (domain)
if (arrayContains(testEmail.split("#")[1], emailsArray))
{
// this will fire as john#liberty.edu matches liberty.edu in emailsArray
console.log("emailsArray contains domain");
}
else
{
console.log("emailsArray does not contain domain");
}
// function to check if an item is contained in an array
function arrayContains(item, array)
{
return (array.indexOf(item) > -1);
}
Complete JSFiddle example here.
Notes:
you can ignore the first two lines of code as I'm guessing you're getting your JSON data from a web response
an assumption is being made that testEmail adheres to the format of an email address; you might need to implement some kind of validation to verify that the string being input is an actual email
we split testEmail by the # character and get the second part of the result (which will be at index 1, since arrays are zero-based) using String.prototype.split()
the emailsArray array is created using the Array.prototype.map() function
arrayContains uses the String.prototype.indexOf() method to check if testEmail exists in emailsArray
I think I've clarified what every line of code in the example does. You can now take it and adjust it to your own requirements—and even better, improve it.
Instead of regex, you can iterate through the array of schools, and match the domain like this:
var schools = [
{"School":"Ivy Tech Community College","Email":"ivytech.edu"},
{"School":"Liberty University","Email":"liberty.edu"},
{"School":"Miami Dade College","Email":"mdc.edu"},
{"School":"Lone Star College","Email":"lonestar.edu"},
{"School":"Ashford University","Email":"ashford.edu"}
]
function validate(email) {
var domain = email.split('#').pop();
for(var i = 0; i < schools.length; i++) {
if(domain === schools[i].Email) return schools[i].School;
}
return 'Domain Not Found';
}
You can replace schools[i].School with true and 'Domain Not Found' with false to just check with it exists.
Example: https://jsfiddle.net/TheQueue841/gwhkq520/
Something like trashrOx mentioned would work:
var edus = [
{"School":"Ivy Tech Community College","Email":"ivytech.edu"},
{"School":"Liberty University","Email":"liberty.edu"},
{"School":"Miami Dade College","Email":"mdc.edu"},
{"School":"Lone Star College","Email":"lonestar.edu"},
{"School":"Ashford University","Email":"ashford.edu"}
];
var emails = ['matty.fake#lonestar.edu','himom#mdc.edu','randomguy#yahoo.com'];
emails.forEach(function(element,index) {
var domain = element.substring(element.indexOf('#') + 1);
var match = 'none';
if (domain) {
edus.forEach(function(element,ind) {
if (element.Email === domain) {
match = element.School;
}
});
console.log(element + ' matched ' + match);
}
});
// matty.fake#lonestar.edu matched Lone Star College
// himom#mdc.edu matched Miami Dade College
// randomguy#yahoo.com matched none
Use Array.prototype.some() if you only want to validate.
some() executes the callback function once for each element present in the array until it finds one where callback returns a truthy value (a value that becomes true when converted to a Boolean). If such an element is found, some() immediately returns true. Otherwise, some() returns false. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
var schools = [
{"School":"Ivy Tech Community College","Email":"ivytech.edu"},
{"School":"Liberty University","Email":"liberty.edu"},
{"School":"Miami Dade College","Email":"mdc.edu"},
{"School":"Lone Star College","Email":"lonestar.edu"},
{"School":"Ashford University","Email":"ashford.edu"}
]
function validate(email) {
var domain = email.split('#').pop();
return schools.some(function(school) {
return school.Email === domain;
});
}
validate('test#ashford.edu');

Dictionary with arrays of keys and values

This question is in regards to javascript or jQuery, whichever will get the job done better.
What I want to do is create an object similar to the following:
var prodItems = [
{
"product": "prod1",
"item": ["prod1Item1", "prod1Item2"]
},
{
"product": "prod2",
"item": ["prod2Item1", "prod2Item2", "prod2Item3", "prod2Item4"]
}
];
with this I can access the members like this:
prodItems[1]["product"] is "prod2"
prodItems[1]["item"][0] is "prod2Item1"
I would like to create this list dynamically and I am stumbling with the syntax, something like:
var menuItems;
menuItems.product[0] = "prod1";
menuItems.product[0].item[0] = "prod1Item1";
Can someone please give me some guidance on how I can do this?
Edit, i want to create a function with something like
returnDict("prod2", "prod2Item3")
this will rearrange it like so:
prodItems = [
{
"product": "prod2",
"item": ["prod2Item3", "prod2Item1", "prod2Item2", "prod2Item4"]
},
{
"product": "prod1",
"item": ["prod1Item1", "prod2Item2"]
}
];
My "guidance" on constructing the object would be to avoid this style of inserting each string separately:
menuItems.product[0].product = "prod1";
menuItems.product[0].item[0] = "prod1Item1";
because this involves a lot of writing the same thing over and over, which is more error-prone and less readable/maintainable. I would prefer inserting more coarse-grained objects:
menuItems.product[0] = {
product: "prod1",
item: ["prod1Item1"];
}
Edit: Your edit is asking a completely different question, but it sounds like what you want to do is sort the elements of prodItems based on their "product" properties, then do the same thing for the "items" array inside the elements.
I think the simplest way to do this would be to use Array.sort() with a custom comparison function that returns -1 on the element you want to see at the top. Something like this (hastily written and untested):
function returnDict(product, item) {
prodItems = prodItems.sort(function(a, b) {
if(a.product === product) {
return -1;
} else if(b.product === product) {
return 1;
} else {
return 0;
}
});
prodItems[0].items = prodItems[0].items.sort(function(a, b) {
if(a === item) {
return -1;
} else if(b === item) {
return 1;
} else {
return 0;
}
});
return prodItems;
}
var menuItems = [];
menuItems.push({product:"prod1",item:[]})
menuItems[menuItems.length-1].item.push("product1Item1")
menuItems[menuItems.length-1].item.push("product1Item2")
menuItems.push({product:"prod2",item:[]})
menuItems[menuItems.length-1].item.push("product2Item1")
menuItems[menuItems.length-1].item.push("product2Item2")
menuItems[menuItems.length-1].item.push("product2Item3")
menuItems[menuItems.length-1].item.push("product2Item4")
var prodItems = [
{
"product": "prod1",
"item": ["prod1Item1", "prod2Item2"]
},
{
"product": "prod2",
"item": ["prod2Item1", "prod2Item2", "prod2Item3", "prod2Item4"]
}
];
alert(prodItems[0].product);
for(var i = 0; i < prodItems.length; i++) {
alert(prodItems[i].product);
}
I see your question has been answered, but I want to suggest a small improvement to keep your code more DRY (Do not Repeat Yourself). You can use a simple function that will save you some extra typing when adding new objects.
var prodItems=[];
function addProduct(productName, items){
var product={
product: productName,
items: items
};
prodItems.push(product);
};
//sample use
addProduct("prod2",["prod2Item3", "prod2Item1", "prod2Item2", "prod2Item4"])
This will definitely also become more flexible if you need to change the object structure at some later point.

How to get count of elements according to the value contained in javascript

I have a json array contains many elements. A part of the array is given:
var some_array = {
"0":{
"picture":"qwerty.jpg",
"textofPicture":"comment for Picture 5",
"picNo":1,
"id":25,
"uid0":125,
"uid1":123,
"uid2":126,
"uid3":127,
"uid4":124,
"u0":"149",
"u1":"80",
"u2":"71",
"u3":"108",
"u4":"158",
"accepted":false,
"su":"",
"point":0
},
"1":{
"picture":"qwerty.jpg",
"textofPicture":"comment for Picture 3",
"picNo":2,
"id":23,
"uid0":113,
"uid1":117,
"uid2":116,
"uid3":114,
"uid4":115,
"u0":"62",
"u1":"58",
"u2":"115",
"u3":"138",
"u4":"106",
"accepted":false,
"su":"",
"point":0
}
}
I want to count how many accepted key's value is true. I am sure there is good way to do this. I do not want to dive into loops.
One way to obtain the count you're looking for is like this
var count = 0;
var some_array = [
0 : {
accepted : false
},
1 : {
accepted : true
}
];
for (var i in some_array) {
if (some_array[i].accepted === true) {
count++;
}
}
return count;
Let me know if this helps and makes since to you. if need be i can make plunker for a visual.

Categories

Resources