Verify all columns of the array for a determined pattern - javascript

I have the following javascript code
var list = [
{
Date : '2014-12-31 12:23:43',
DateStart: '1980-12-30 23:43:42',
Name: 'Kate',
...
...
},
{
Date : '1978-05-21 23:43:65',
DateStart: '1973-04-06 12:34:09',
Name: 'John',
...
...
}
];
And the following code to verify for regex pattern:
for (var i in list) {
var data = [];
if (/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/.test(list[i].?)) {
data.push({Data: list[i].Data });
}
}
The variable i from the above code is to interact with each line of the array.
How can I interact through for loops with each line and column without having to specify this in the question mark from the above code?
What can I do to all columns be verified for the date pattern?
Making the array date stay only with the values
2014-12-31 12:23:43,
1980-12-30 23:43:42,
1978-05-21 23:43:65,
1973-04-06 12:34:09

How can I interact through for loops with each line and column without having to specify this in the question mark from the above code?
You have to specify the field you want to access, how else should the interpreter be able to know what you want to access?
If you want to avoid using an indexer you can use external libraries like underscore.js to iterate over the collection:
http://underscorejs.org/#each
_.each(list, function(item) {
// validate item.Date and item.DateStart here
});
Alternatively there is a very concise post about this topic here: For-each over an array in JavaScript?

Was this what I wanted
for (var j = 0; j < list.length; j++) {
for (p in list[j]) {
if (/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/.test(list[j][p])) {
data.push({Data: list[j][p] });
}
}
}

Related

Get keys from javascript array

Hello i have selectbox to show from javascript array.
<h6><strong>Brand</strong></h6>
<select data-placeholder="Brand..." multiple id="brand" style="width:200px;height:50px;margin: 0;">
<script language="javascript">print_brand1("brand");</script>
</select>
But when i choose one of selectbox data then it get values. Here is javascript code
var brand_arr = new Array(
1:"Acer",
2:"Dell"
);
function print_brand1(brand_id){
var option_str = document.getElementById(brand_id);
option_str.length=0;
option_str.selectedIndex = 0;
for (var i=0; i<brand_arr.length; i++) {
option_str.options[option_str.length] = new Option(brand_arr[i],brand_arr[i]);
}
}
How do i get keys (not values) when i choose one of selectbox data?
Your code will not work in its current state, however if you insist on keeping your current array structure you would need:
var brand_arr = {
1: "Acer",
2: "Dell"
};
Which syntactically makes little sense, assigning a key of 1/2 makes little sense when you could just get this number by using the current index + 1.
Note that with the changes above, in order to assign the keys 1 and 2 we are having to iterate over a Javascript Object and not a Javascript Array.
If you wanted to print 1 and 2 you could then do:
for(var k in brand_arr) {
if(brand_arr.hasOwnProperty(k)) {
console.log(k); // key
console.log(brand_arr[k]); // value
}
}
Although this answers your problem, I would still consider the structure of your data, it would make much more sense to have something like:
var brand_arr = [
{ brand: 'Acer', price: 200 },
{ brand: 'Dell', price: 200 }
];
Note how in the above example we can add extra details about that brand in the JSON. We could then iterate over the brand array to get more detail about each brand in a much more readable format opposed to a user assigned index and its name.

jQuery getJSON print array where name is string

I have some good practice with using php and mysql, and am now starting with JSON.
I've made a simple json index containing paths to folders, and items inside them:
{ "foldery" : [
{
"foName": "website/img/bg",
"files" : [
"website/img/bg/bg1.jpeg",
"website/img/bg/bg2.jpg",
"website/img/bg/bg3.jpg",
"website/img/bg/bg4.jpeg"
]
},
{
"foName": "website/img/post1",
"files" : [
"website/img/post1/a.jpeg",
"website/img/post1/b.jpg",
"website/img/post1/c.jpeg",
"website/img/post1/d.jpg"
]
}
]
}
Now here is my jquery, for now returning a big mess of data, somewhere including the info about the contents inside:
$.getJSON("nameindex.json", function(data) {
console.log(data);
});
What I would like it to do, in mySql looks like this:
SELECT files FROM foldery WHERE foName = "website/img/post1"
Thus the result, would be an array containing all the files inside post1.
Unfortunately tho, after 2 hours of attempts I have nothing more than the simple console.log code.
Any help would be gladly appreciated
You need to iterate over your array and check forName to equality
function select(o, foName) {
var length = o.foldery.length;
for(var i = 0; i < length; i++){
if (o.foldery[i].foName == foName) {
return o.foldery[i].files;
}
}
}
var result = select(o, "website/img/post1")
console.log(result);
Result
[ 'website/img/post1/a.jpeg',
'website/img/post1/b.jpg',
'website/img/post1/c.jpeg',
'website/img/post1/d.jpg' ]

Group objects in array by property

I have just started to pick up coding seriously. :)
I came across a problem that seems too complicated for me.
How to group the following products by promotions type?
var data = [
{
name:'product1',
price:'40',
promotion:[
{
name:'Buy 3 get 30% off',
code:'ewq123'
},
{
name:'Free Gift',
code:'abc140'
}
]
},
{
name:'product2',
price:'40',
promotion:[
{
name:'Buy 3 get 30% off',
code:'ewq123'
}
]
},
{
name:'product3',
price:'40',
promotion:[
{
name:'Buy 3 get 30% off',
code:'ewq123'
}
]
},
{
name:'product4',
price:'40'
},
{
name:'product5',
price:'40',
promotion:[
{name:'30% off', code:'fnj245'}
]
},
{
name:'product6',
price:'0',
promotion:[
{
name:'Free Gift',
code:'abc140'
}
]
}
];
I would like to get result in the following format
result =[
{
name : 'Buy 3 get 30% off',
code: 'ewq123',
products: [
... array of products
]
},
{
name : '30% off',
code: 'fnj245',
products: [
... array of products
]
},
{
...
}
];
I am able to get a list of products by promotion code, but how can I make it generic?
function productHasPromo(product, promotion){
if(!product.hasOwnProperty('promotion')) return false;
var productPromo = product.promotion;
for(var i=0; i<productPromo.length; i++){
if(productPromo[i].code === promotion){
return true;
}
}
return false;
}
function groupProductByPromo(products, promotion){
var arr = [];
for(var i=0; i<products.length; i++){
if(productHasPromo(products[i], promotion)){
arr.push(products[i]);
}
}
return arr;
}
Explanation
You could write a function that loops through your array and search for the unique values within a specified property. That is easily done when working with simple data types, but can be done with more complex structures as arrays of objects (like in your example), using a helper grouping function.
Since you also need the output to be in a specific format after the grouping, we will have to work on a transformer also. This transformer will receive the original data and the unique values extracted by the grouping function, and will generate the desired output.
The following functions were used in the example:
Array.prototype.groupBy = function (property, grouping, transformer) {
var values = [];
this.forEach(function (item) {
grouping.call(this, item, property).forEach(function (item) {
if (!values.contains(property, item[property])) {
values.push(item);
}
});
});
return transformer.call(this, values);
};
Array.prototype.contains = function (key, value) {
return this.find(function (elm) {
return elm[key] === value;
});
};
function transformerFunction(values) {
this.forEach(function (item) {
if (!item.promotion) return;
item.promotion.forEach(function (promotion) {
values.forEach(function (option) {
if (option.code === promotion.code) {
if (option.products) {
option.products.push(item);
} else {
option.products = [item];
}
}
});
});
});
return values;
}
function groupingFunction(item, property) {
if (!item.promotion) return [];
var values = [];
item.promotion.forEach(function (promotion) {
if (!values.contains(property, promotion[property])) {
values.push(promotion);
}
});
return values;
}
Usage as follows:
var items = data.groupBy('code', groupFunction, transformFunction);
Example
Check the example i've prepared at jsfiddle
Welcome to the coding world. A lot of people start off with a problem by trying to write some code, then they wonder why it doesn't work and scratch their heads, don't know the basics of debugging it, and then post here to SO. They're missing the crucial first step in programming which is to figure out how you are going to do it. This is also called designing the algorithm. Algorithms are often described using something called pseudo-code. It has the advantage that it can be looked at and understood and established to do the right thing, without getting bogged down in all the mundane details of a programming language.
There are some algorithms that are figured out by some very smart people--like the Boyer-Moore algorithm for string matching--and then there are other algorithms that programmers devise every day as part of their job.
The problem with SO is that all too often someone posts a question which essentially about an algorithm, and then all the keyboard-happy code jockeys pounce it and come up with a code fragment, which in many cases is so contorted and obtuse that one cannot even see what the underlying algorithm is.
What is the algorithm you propose for solving your problem? You could post that, and people would probably give you reasonable comments, and/or if you also give an actual implementation that doesn't work for some reason, help you understand where you've gone wrong.
At the risk of robbing you the pleasure of devising your own algorithm for solving this problem, here's an example:
Create an empty array for the results.
Loop through the products in the input.
For each product, loop through its promotions.
Find the promotion in the array of results.
If there is no such promotion in the array of results, create a new one, with an empty list of products.
Add the product to the array of products in the promotion entry in the array.
In pseudo-code:
results = new Array // 1
for each product in products (data) // 2
for each promotion in promotions field of product // 3
if results does not contain promotion by that name // 4
add promotion to results, with empty products field // 5
add product to products field of results.promotion // 6
If we believe this is correct, we can now try writing this in JavaScript.
var result = []; // 1
for (var i = 0; i < data.length; i++) { // 2
var product = data[i];
var promotions = product.promotion;
for (var j = 0; j < promotions.length; j++) { // 3
var promotion = promotions[i];
var name = promotion.name;
var result_promotion = find_promotion_by_name(name);
if (!result_promotion) { // 4
result_promotion = { name: name, products: [], code: promotion.code };
result.push(result_promotion); // 5
}
result_promotion.products.push(name); // 6
}
}
This code is OK, and it should get the job done (untested). However, it is still a bit unreadable. It does not follow the pseudo-code very closely. It somehow still hides the algorithm. It is hard to be sure that it is completely correct. So, we want to rewrite it. Functions like Array#foreach make it easier to do this. the top level can simply be:
var result = [];
data.forEach(processProduct);
In other words, call the processProduct function for each element of data (the list of products). It will be very hard for this code to be wrong, as long as `processProduct is implemented incorrectly.
function processProduct(product) {
product.promotion.forEach(processPromotion);
}
Again, this logic is provably correct, assuming processPromotion is implemented correctly.
function processPromotion(promotion) {
var result_promotion = getPromotionInResults(promotion);
result_promotion.products.push(name);
}
This could hardly be clearer. We obtain the entry for this promotion in the results array, then add the product to its list of products.
Now we need to simply implement getPromotionInResults. This will include the logic to create the promotion element in the results array if it doesn't exist.
function getPromotionInResults(promotion) {
var promotionInResults = findPromotionInResultsByName(promotion.name);
if (!promotionInResults) {
promotionInResults = {name: promotion.name, code: promotion.code, products: []};
result.push(promotionInResults);
}
return promotionInResults;
}
This also seems demonstrably correct. But we still have to implement findPromotionInResultsByName. For that, we can use Array#find, or some equivalent library routine or polyfill:
function findPromotionInResultsByName(name) {
return result.find(function(promotion) {
return promotion.name === name;
});
}
The entire solution is thus
function transform(data) {
// Given a product, update the result accordingly.
function processProduct(product) {
product.promotion.forEach(processPromotion);
}
// Given a promotion, update its list of products in results.
function processPromotion(promotion) {
var result_promotion = getPromotionInResults(promotion);
result_promotion.products.push(name);
}
// Find or create the promotion entries in results.
function getPromotionInResults(promotion) {
var promotionInResults = findPromotionInResultsByName(promotion.name);
if (!promotionInResults) {
promotionInResults = {name: promotion.name, code: promotion.code, products: []};
result.push(promotionInResults);
}
return promotionInResults;
}
// Find an existing entry in results, by its name.
function findPromotionInResultsByName(name) {
return result.find(function(promotion) {
return promotion.name === name;
});
}
var result = [];
data.forEach(processProduct);
return result;
}
Ok, after a few hours of works, with lots of help online and offline, I finally made it works. Thanks for the people who has helped.
Please do comment if you have a more elegant solution, always love to learn.
For people who ran into similar problem:
Here is my solution
function groupProductsByPromo(data){
var result = [];
// filter only product with promotion
var productsWithPromo = data.filter(function(product){
return product.hasOwnProperty('promotions');
});
// create promotions map
var mappedProducts = productsWithPromo.map(function(product) {
var mapping = {};
product.promotions.forEach(function(promotion) {
mapping[promotion.code] = {
promotion: promotion
};
});
return mapping;
});
// reduce duplicates in promotion map
mappedProducts = mappedProducts.reduce(function(flattenObject, mappedProducts) {
for (var promoCode in mappedProducts) {
if (flattenObject.hasOwnProperty(promoCode)) {
continue;
}
flattenObject[promoCode] = {
code: promoCode,
name: mappedProducts[promoCode].promotion.name
};
}
return flattenObject;
}, {});
// add products to promo item
for(var promoCode in mappedProducts){
mappedProducts[promoCode].products = productsWithPromo.filter(function(product){
return product.promotions.some(function(promo){
return promo.code === promoCode;
});
});
result.push(mappedProducts[promoCode]);
}
return result;
}
Check out lodash - a nifty library for doing all sorts of transforms.
lodash.groupBy is what you're looking for.

How to iterate through nested array of JSON in jQuery?

I have a data in json format getting from PHP script the data is coming in following format as follows:
[{
"type":"checkbox",
"grid-name":"Sports",
"values":["Cricket","Football"],
"input":[{"Cricket":2},{"Football":1}]
},
{"type":"checkbox",
"grid-name":"Hobbies",
"values":["Playing Chess","Swimming"],
"input":[{"Playing Chess":1},{"Swimming":2}]
},
{"type":"radiobutton",
"grid-name":"Gender",
"values":["Male","Female"],
"input":[{"Male":3},{"Female":0}]
},
{"type":"radiobutton",
"grid-name":"Citizen",
"values":["Indian","NRI"],
"input":[{"Indian":3},{"NRI":0}]
},
{"type":"number",
"grid-name":"Age",
"input":["24","23","23"]
},
{"type":"select",
"grid-name":"City",
"values":["Satara","New york","Korea"],
"input":[{"Satara":1},{"New york":1},{"Korea":1}]
}]
i want to capture the values & input array. How to access through nested array?
jQuery:
$.each(yourObject, function( index, value ) {
console.log(value.values);
console.log(value.input);
});
Native js (but better don't use it, accordingly to this):
for (index in yourObject) {
console.log(yourObject[index].values);
console.log(yourObject[index].input);
}
Native js, another example:
for (var i = 0; i < yourObject.length; i++) {
console.log(yourObject[i].values);
console.log(yourObject[i].input);
}
You're looking for $.each. This will allow you to loop through object-arrays.
https://api.jquery.com/jquery.each/
If you're also asking how to capture the values and you have the raw text, you're also looking for $.parseJSON
https://api.jquery.com/jquery.parsejson/

underscore find method issue on array of objects

I have following array of objects
var ppl = [
{
name: "John",
content: "<p>description</p>"
},
{
name: "Mike",
content: "<p>Desc</p>"
},
{
name: "Steve",
content: "html"
},
{
name: "Michael",
content: "<p>description</p>"
}
];
What I am doing is to display above array. Then when user clicks on name return his content. Like following
$('a.ppl').on('click', function (e) {
e.preventDefault();
var text = $(this).text();
var content = _.find(ppl, function (desc) { if (desc.name === text) return desc.content; });
console.log(content);
});
What above code does is it finds the content of the person clicked however it returns the entire object of that person e.g. when John is clicked the his entire object {
name: "John",
content: "<p>description</p>"
} is returned by the _.find() function. I just need the content. How can I return content only?
If I were you I would simply do a loop:
var length = ppl.length;
var findcat = function(){
for (var a = 0; a < length; a++) { if(ppl[a].name==text){return ppl[a].content} };
}
var content = findcat();
rather than using underscore.js .
Or if you really want to use underscore.js, change it to this:
var content = _.find(ppl, function (desc) { if (desc.name === text) return desc; });
content = content.content;
and it will work.
Updates (regarding HTML strings in json):
It is okay to store them in json as these HTML strings will simply be considered as normal strings data (just don't forget to escape characters like quotation and forward slash). When real HTML elements are being created from these strings (using jquery functions like .html(string), append(string) ), the browser will need to render these new contents and it may cause a slow performance comparing to leaving all the page-rendering at the start for the browser, but the difference will be pretty subtle. So in terms of performance, it is always okay to have them in json. But in terms of security, you should be careful when there were HTML markup in your data because you are making XSS easier to be accomplished. (Here is a wikipedia article that provides more details on XSS, also known as Cross-site scripting.)
I don't think you need an array here. A simpler and more efficient way would be to use names as properties.
var ppl = {"John": "<p>description</p>", "Mike": "<p>Desc</p>" };
$('a.ppl').on('click', function (e) {
e.preventDefault();
var text = $(this).text();
console.log(ppl[text]);
});
This is the expected Behavior of find operator which returns whole found item ! , why dont use content.content
the _.find looks through each value in the list, returning the first one that passes a truth test, when you return desc.content, it is evalued to true, so the desc object is return. so you can't return inside the find. but you can just access the content as desc.content. here is jsfiddle code:
$('a.ppl').on('click', function (e) {
e.preventDefault();
var text = $(this).text();
var desc = _.find(ppl, function (desc) {
return desc.name === text;
});
console.log(desc.content);
});

Categories