JS string counter - javascript

I want this code to count the number of times that category and message are in the bottom string, regardles of the different id number. The code just gives me the last one.
It is quite messy, sry. Thanks for your help.
Kind regards.
counter = function() {
var value = $('#text').val();
if (value.length == 0) {
$('#wordCount').html(0);
return;
}
var regex = /\s+/gi;
var wordCount = value.trim().replace(regex, ' ').split(' ').length;
};
$(document).ready(function() {
var obj = {"data" : {
"from": {
"category": "cat1",
"id": 1,
"message": "WIZ1"
},
"from": {
"category": "cat2",
"id": 2,
"message": "WIZ2"
},
"from": {
"category": "cat3",
"id": 3,
"message": "WIZ3"
},
"from": {
"category": "cat4",
"id": 4,
"message": "WIZ3"
},
}
};
$.each(obj, function() {
$.each(this, function(name, value) {
$("#result").append(name + '=' + value.category);
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="result">Words: <span id="wordCount">0</span>
<br/>
</div>

You have a single object with the "from" property being overwritten 4 times. It looks like what you wanted was to instead have an array, like the example below.
I also changed the code to actually capture the categories and messages, like the description in your post, after the loops those objects will have the count by message and count by category.
counter = function() {
var value = $('#text').val();
if (value.length == 0) {
$('#wordCount').html(0);
return;
}
var regex = /\s+/gi;
var wordCount = value.trim().replace(regex, ' ').split(' ').length;
};
$(document).ready(function() {
var obj = {"data" : [
{
"category": "cat1",
"id": 1,
"message": "WIZ1"
},
{
"category": "cat2",
"id": 2,
"message": "WIZ2"
},
{
"category": "cat3",
"id": 3,
"message": "WIZ3"
},
{
"category": "cat4",
"id": 4,
"message": "WIZ3"
},
]
};
var categories = {};
var messages = {}
$.each(obj, function() {
$.each(this, function(name, value) {
if (!categories[value.category]) categories[value.category] = 0;
categories[value.category] += 1;
if (!messages[value.message]) messages[value.message] = 0;
messages[value.message] += 1;
$("#result").append(name + '=' + value.category);
});
});
console.log(categories);
console.log(messages);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="result">Words: <span id="wordCount">0</span>
<br/>
</div>

Each of the items in the JS object have the same key ('from').
That's causing each one to overwrite the previous, which is why it's only finding the last one.
{
"data": {
"from1": {
"category": "cat1",
"id": 1,
"message": "WIZ1"
},
"from2": {
"category": "cat2",
"id": 2,
"message": "WIZ2"
},
"from3": {
"category": "cat3",
"id": 3,
"message": "WIZ3"
},
"from4": {
"category": "cat4",
"id": 4,
"message": "WIZ3"
}
}
}
This will allow it to iterate through each item as there will now be four items present.

Related

Comparing an array with another array plus adding a counter

So I'm reformatting my data and I noticed that my data isn't quite getting restructured the way I want it to. I noticed that my results come back as
[
{
"name": "sites",
"parent": null,
"count": 3
},
{
"name": "group1",
"parent": "sites",
"count": 3
},
{
"name": "bk",
"parent": "group1",
"count": 3
},
{
"name": "sitepages",
"parent": "bk",
"count": 1
},
{
"name": "home.aspx",
"parent": "sitepages",
"count": 1
}
]
It isn't grabbing my "not matches". I've spent so much time looking it over and I'm coming to a blank. It should be
[
{
"name": "sites",
"parent": null,
"count": 3
},
{
"name": "group1",
"parent": "sites",
"count": 3
},
{
"name": "bk",
"parent": "group1",
"count": 3
},
{
"name": "sitepages",
"parent": "bk",
"count": 1
},
{
"name": "home.aspx",
"parent": "sitepages",
"count": 1
},
{
"name": "tester",
"parent": "bk",
"count": 1
},
{
"name": "tester",
"parent": "home.aspx",
"count": 1
},
{
"name": "_layouts",
"parent": "bk",
"count": 1
},
{
"name": "15",
"parent": "_layouts",
"count": 1
},
{
"name": "upload.aspx",
"parent": "15",
"count": 1
},
]
I believe something is missing in my loop.
var testArr = [
{
Author: { Title: "Mitchell" },
BrowserType: "FireFox",
Created: "2017-04-25T16:39:40Z",
pathname: "sites/group1/bk/sitepages/home.aspx"
},
{
Author: { Title: "Pierre" },
BrowserType: "Opera",
Created: "2017-04-25T16:39:40Z",
pathname: "sites/group1/bk/tester/home.aspx"
},
{
Author: { Title: "Mizell" },
BrowserType: "IE",
Created: "2017-04-25T16:47:02Z",
pathname: "sites/group1/bk/_layouts/15/upload.aspx"
}
];
function reduceData(data) {
var root = null;
var newArr = null;
var itemContainer = [];
var masterArr = [];
var filteredArr = [];
data.forEach(function (props, idx) {
//check the last character of the pathname is "/" and removes it
if (props.pathname.charAt(props.pathname.length - 1) === "/") {
props.pathname = props.pathname.substring(0, props.pathname.length - 1);
}
//lowercase the pathname + split into strings
props.pathname = props.pathname.toLowerCase().split("/");
//format the pathname
var lastItem = "";
newArr = props.pathname.reduce(function (acc, props, index) {
if (acc.length === 0) {
acc.push({ name: props, parent: null, count: 1 });
lastItem = props;
} else {
acc.push({ name: props, parent: lastItem, count: 1 });
lastItem = props;
}
return acc;
}, []);
//The first iteration
if (idx === 0) {
itemContainer = newArr;
} else {
for (var i = 0; i < itemContainer.length; i++) {
// Loop for newArr
for (var j = 0; j < newArr.length; j++) {
//compare the element of each and every element from both of the arrays
//console.log(masterArr[i], newArr[j]);
if (
itemContainer[i].name === newArr[j].name &&
itemContainer[i].parent === newArr[j].parent
) {
//Match
masterArr[i] = {
name: itemContainer[i].name,
parent: itemContainer[i].parent,
count: itemContainer[i].count++
};
} else {
//Doesn't Match
masterArr[i] = {
name: itemContainer[i].name,
parent: itemContainer[i].parent,
count: itemContainer[i].count
};
}
}
}
}
});
console.log(masterArr)
}
reduceData(testArr)
ok.. I revamp your code a little..
delete the if else after the //The first iteration, and use this instead..
newArr.forEach((newEl) => {
const matchIdx = masterArr.findIndex((masterEl) => masterEl.name === newEl.name && masterEl.parent === newEl.parent);
if(matchIdx < 0){
masterArr.push(newEl);
}
else {
masterArr[matchIdx].count = masterArr[matchIdx].count + 1;
}
});

Convert polyhierarchy parent-child relationship to array (tree) - javascript or jquery

var data = [
{
"text": "BEHIND A COMMON MEAL: POLYPHENOLS IN FOOD ",
"id": "445",
"parentid": ""
},
{
"text": "2.2 First Course: Pasta With Tomato Sauce (Polyphenols in Wheat Bran and Tomato Byproducts)",
"id": "441",
"parentid": "445"
},
{
"text": "2.3 A Fresh Side Dish: Mixed Salad (Polyphenols From Fennel, Carrot)",
"id": "442",
"parentid": "445"
},
{
"text": "hello mr.sujai",
"id": "448",
"parentid": "445"
},
{
"text": "polyhierarchy",
"id": "449",
"parentid": "445"
},
{
"text": "INTRODUCTION",
"id": "452",
"parentid": ""
},
{
"text": "1.2 The Tight Biochemical Connection Between Vegetables and Their Byproducts",
"id": "440",
"parentid": "452"
},
{
"text": "OTHER OFF-THE-MENU MISCELLANEOUS",
"id": "454",
"parentid": ""
},
{
"text": "SOMETHING TO DRINK",
"id": "456",
"parentid": ""
},
{
"text": "3.1 Orange Juice (Polyphenols From Orange Byproducts)",
"id": "443",
"parentid": "456"
},
{
"text": "3.2 Wine (Polyphenols From Grape and Wine Byproducts)",
"id": "444",
"parentid": "456"
},
{
"text": "understandings",
"id": "451",
"parentid": "456"
},
{
"text": "Polyphenols",
"id": "453",
"parentid": "451"
},
{
"text": "this is test",
"id": "458",
"parentid": "455"
},
{
"text": "polyhierarchy",
"id": "449",
"parentid": "458"
},
{
"text": "hello",
"id": "447",
"parentid": "449"
},
{
"text": "hi",
"id": "459",
"parentid": "447"
},
{
"text": "polyhierarchy",
"id": "449",
"parentid": "459"
},
{
"text": "testing",
"id": "457",
"parentid": "458"
},
{
"text": "hi test",
"id": "450",
"parentid": "457"
},
{
"text": "speech",
"id": "446",
"parentid": "450"
}]
function jsonTree() {
// Keep a fast lookup dictionary
var dictionary = {};
for (var i = 0; i < data.length; i++) {
dictionary[data[i].id] = data[i];
}
for (var i = 0; i < data.length; i++) {
if (data[i].parentid == 449) {
var test = "";
}
if (data[i].parentid) {
var parent = dictionary[data[i].parentid];
arrData = parent;
if (parent) {
if (!parent.children) {
parent.children = [];
}
parent.children.push(data[i]);
// arrData.children.push(data[i]);
}
}
}
var arrData = [];
for (var i = 0; i < data.length; i++) {
if (data[i].parentid == 455) {
arrData.push(data[i]);
}
}
document.getElementById("test").innerHTML = JSON.stringify(arrData);
return false;
}
polyhierarchy term having different parent.
for (var i = 0; i < data.length; i++) {
dictionary[data[i].id] = data[i];
}
in this place same id is replaced. polyhierarchy having id is 449. when add to dictionary it is replaced.
Tree structure should be
1. BEHIND A COMMON MEAL: POLYPHENOLS IN FOOD
polyhierarchy
2. this is test
polyhierarchy
hello
hi
polyhierarchy
i need array with parent, child relationship.
There are a few mistakes.
You have duplicate id's for your polyhierarchie element. Because you're building a dictionary to lookup your ids, you're overwriting your child element the second/subsequent time you add it to your object.
{
"text": "polyhierarchy",
"id": "449", //<-- duplicate
"parentid": "459"
}
You have non existant parentIds.
{
"text": "SOMETHING TO DRINK",
"id": "456",
"parentid": "455" // <--- doesn't exist
}
The code got a little more complex than anticipated because of those two issues.
function mapData (data) {
//build a dictionary for: id -> [eles]
var map = data.reduce ((obj, ele) => {
obj[ele.id] = [ //let's make the lookup an array, to support multiple elements with the same id
...obj[ele.id] || [], //keep the existing elements or initialize it to an array
{...ele, children: []}
];
return obj
}, {});
return Object.keys (map).reduce ((arr, key) => {
let eles = map [key] || []; //process all elements
eles.forEach (ele => {
let parents = map [ele.parentid] || [];
let parent = parents [0];
if (!parent) {
parent = map [ele.parentid] = {children: [], root: true}
}
parent.children.push (ele);
if (parent.root && !~arr.indexOf (parent)) arr.push (parent);
});
return arr;
},[])
}
console.log (mapData (data))

Use array as sort order

I want to use an array of strings as template how to order other arrays.
var sort = ["this","is","my","custom","order"];
and then i want to sort an array of objects depending on a key (content) by that order:
var myObjects = [
{"id":1,"content":"is"},
{"id":2,"content":"my"},
{"id":3,"content":"this"},
{"id":4,"content":"custom"},
{"id":5,"content":"order"}
];
so that my result is:
sortedObject = [
{"id":3,"content":"this"},
{"id":1,"content":"is"},
{"id":2,"content":"my"},
{"id":4,"content":"custom"},
{"id":5,"content":"order"}
];
how would i do that?
You can do something like this with help of sort() and indexOf()
var sort = ["this", "is", "my", "custom", "order"];
var myObjects = [{
"id": 1,
"content": "is"
}, {
"id": 2,
"content": "my"
}, {
"id": 3,
"content": "this"
}, {
"id": 4,
"content": "custom"
}, {
"id": 5,
"content": "order"
}];
var sortedObj = myObjects.sort(function(a, b) {
return sort.indexOf(a.content) - sort.indexOf(b.content);
});
document.write('<pre>' + JSON.stringify(sortedObj, null, 3) + '</pre>');
you need to use .map
var sort = ["this", "is", "my", "custom", "order"];
var myObjects = [{
"id": 1,
"content": "is"
}, {
"id": 2,
"content": "my"
}, {
"id": 3,
"content": "this"
}, {
"id": 4,
"content": "custom"
}, {
"id": 5,
"content": "order"
}];
var myObjectsSort = sort.map(function(e, i) {
for (var i = 0; i < myObjects.length; ++i) {
if (myObjects[i].content == e)
return myObjects[i];
}
});
document.write('<pre>' + JSON.stringify(myObjectsSort , null, 3) + '</pre>');
Create a new array and place the every object from myObjects considering index of the sort
Try this:
var sort = ["this", "is", "my", "custom", "order"];
var myObjects = [{
"id": 1,
"content": "is"
}, {
"id": 2,
"content": "my"
}, {
"id": 3,
"content": "this"
}, {
"id": 4,
"content": "custom"
}, {
"id": 5,
"content": "order"
}];
var newArr = [];
myObjects.forEach(function(item) {
var index = sort.indexOf(item.content);
newArr[index] = item;
});
console.log(newArr);
<script src="http://gh-canon.github.io/stack-snippet-console/console.min.js"></script>
I suggest to use an object for the storing of the sort order.
var sort = ["this", "is", "my", "custom", "order"],
sortObj = {},
myObjects = [{ "id": 1, "content": "is" }, { "id": 2, "content": "my" }, { "id": 3, "content": "this" }, { "id": 4, "content": "custom" }, { "id": 5, "content": "order" }];
sort.forEach(function (a, i) { sortObj[a] = i; });
myObjects.sort(function (a, b) {
return sortObj[ a.content] - sortObj[ b.content];
});
document.write('<pre>' + JSON.stringify(myObjects, 0, 4) + '</pre>');

Filter values of multiple properties with an array of values

So I really would like to make a duplicate out of my previous failed question because I wasn't really able to explain myself properly and thus didn't get the answer (and haven't really solved my issue).
There is the JSON:
[
{
"id": 2,
"name": "Google",
"country": "Sweden"
},
{
"id": 3,
"name": "Google",
"country": "USA"
},
{
"id": 9,
"name": "Google",
"country": "Ukraine"
},
{
"id": 10,
"name": "Bing",
"country": "Sweden"
}
]
What I failed to do previously I guess is to post what I have so far and explain better what I need. This is what I have right now:
$scope.loadSearchEngines = function ($query) {
return $http.get('search-engines.json', {cache: true}).then(function (response) {
var tags = response.data;
return tags.filter(function (tag) {
return tag.name.toLowerCase().indexOf($query.toLowerCase()) != -1;
});
});
};
This filter restricts me to search through only the name property, while ideally I would like to search through any property (or well, all the properties, rather) and I'd like the filter to work with an array of parameters so that each word would separately look through each property in the object and find a match.
In the previous post a person posted a for loop for it, but that is exactly the kind of unintuitive thing I want to avoid.
I know what I want the result to be but I just can't think of an approach (lodash/underscore seemingly almost does something like this, but I think there is something missing from somewhere or I am really bad at understanding the docs).
Examples:
In case I write "google sweden", it will only show the 1 result, if I write "sweden", it would show the one from google and the one from bing.
In case I write "in", it should show "bINg" and google "ukraINe" I guess.
This seemed like a much less of a hassle at first but I can't really wrap my head around this using a filter. I really don't have any ideas to post because they have been embarrassingly bad and this is a really grey area for me.
From the question it looks as if you want to filter a list where the values in each item contains every keyword:
var keywords = ['Google', 'Sweden'];
var result = _.filter(data, function(item){
return _.every(keywords, function(keyword){
return _.some(item, function(value){
return _.isString(value) && value.indexOf(keyword) != -1;
})
});
});
Perhaps something like this (note, probably not the most efficient one). Doesn't handle lowercase, but it's simple to add.
http://jsfiddle.net/W4QfJ/520/
var stuff = [
{
"id": 2,
"name": "Google",
"country": "Sweden"
},
{
"id": 3,
"name": "Google",
"country": "USA"
},
{
"id": 9,
"name": "Google",
"country": "Ukraine"
},
{
"id": 10,
"name": "Bing",
"country": "Sweden"
}
];
var searchTerm = 'Google Sweden';
var searchTermArr = searchTerm.split(' ');
var results = [];
var obj;
searchTermArr.forEach(function (val, index, arr) {
obj = _(stuff)
.filter(function (s) {
return JSON.stringify(s).indexOf(val) > -1;
}).value();
results = results.concat(obj);
});
console.log(_.unique(results));
Version A shapes the result for the whole data set to the wanted set which iterates throu the search words.
var data = [{
"id": 2,
"name": "Google",
"country": "Sweden"
}, {
"id": 3,
"name": "Google",
"country": "USA"
}, {
"id": 9,
"name": "Google",
"country": "Ukraine"
}, {
"id": 10,
"name": "Bing",
"country": "Sweden"
}];
function search(s) {
var searchA = s.split(' ').map(function (a) { return a.toLowerCase(); });
var result = JSON.parse(JSON.stringify(data));
searchA.forEach(function (a) {
result = result.reduce(function (res, el) {
var i;
for (i in el) {
if (~('' + el[i]).toLowerCase().indexOf(a)) {
res.push(el);
break;
}
}
return res;
}, []);
});
return result;
}
out('search for \'google sweden\'\n' + JSON.stringify(search('google sweden'), null, 4), true);
out('search for \'bing\'\n' + JSON.stringify(search('bing'), null, 4), true);
out('search for \'IN\'\n' + JSON.stringify(search('IN'), null, 4), true);
out('search for \'x\'\n' + JSON.stringify(search('x'), null, 4), true);
function out(s, pre) {
var descriptionNode = document.createElement('div');
if (pre) {
var preNode = document.createElement('pre');
preNode.innerHTML = s + '<br>';
descriptionNode.appendChild(preNode);
} else {
descriptionNode.innerHTML = s + '<br>';
}
document.getElementById('out0').appendChild(descriptionNode);
}
<div id="out0"></div>
Version B with different approach. Here I collect the objects who match the requirements.
var data = [{
"id": 2,
"name": "Google",
"country": "Sweden"
}, {
"id": 3,
"name": "Google",
"country": "USA"
}, {
"id": 9,
"name": "Google",
"country": "Ukraine"
}, {
"id": 10,
"name": "Bing",
"country": "Sweden"
}];
function search(s) {
var searchA = s.split(' ').map(function (a) { return a.toLowerCase(); });
return data.reduce(function (res, el) {
var i, found = 0;
for (i in el) {
found += searchA.some(function (a) {
return ~('' + el[i]).toLowerCase().indexOf(a);
});
}
found === searchA.length && res.push(el);
return res;
}, []);
}
out('search for \'google sweden\'\n' + JSON.stringify(search('google sweden'), null, 4), true);
out('search for \'bing\'\n' + JSON.stringify(search('bing'), null, 4), true);
out('search for \'IN\'\n' + JSON.stringify(search('IN'), null, 4), true);
out('search for \'x\'\n' + JSON.stringify(search('x'), null, 4), true);
function out(s, pre) {
var descriptionNode = document.createElement('div');
if (pre) {
var preNode = document.createElement('pre');
preNode.innerHTML = s + '<br>';
descriptionNode.appendChild(preNode);
} else {
descriptionNode.innerHTML = s + '<br>';
}
document.getElementById('out').appendChild(descriptionNode);
}
<div id="out"></div>

How to select json item from the array

From the below JSON, how can I retrieve title from the note and notes using a for loop and ajax to retrieve?
{
"infos": {
"info": [
{
"startYear": "1900",
"endYear": "1930",
"timeZoneDesc": "daweerrewereopreproewropewredfkfdufssfsfsfsfrerewrBlahhhhh..",
"timeZoneID": "1",
"note": {
"notes": [
{
"id": "1",
"title": "Mmm"
},
{
"id": "2",
"title": "Wmm"
},
{
"id": "3",
"title": "Smm"
}
]
},
"links": [
{ "id": "1", "title": "Red House", "url": "http://infopedia.nl.sg/articles/SIP_611_2004-12-24.html" },
{ "id": "2", "title": "Joo Chiat", "url": "http://www.the-inncrowd.com/joochiat.htm" },
{ "id": "3", "title": "Bake", "url": "https://thelongnwindingroad.wordpress.com/tag/red-house-bakery" }
]
}
I tried out the code below but it doesn't work - it either says:
is null
not an object
length is null
r not an object
var detail = eval(xmlhttprequest.responseText)
var rss = detail.infos.info
for(var i = 0; i<rss.length; i++)
startyear += rss[i].startyear
Use
for (i = 0; i < 3; i++) {
alert(JSON.infos.info[0].note.notes[i].title);
}
TRY IT HERE: JSFIDDLE WORKING EXAMPLE
BTW your JSON is not valid. Use this JSON:
var JSON = {
"infos": {
"info": [
{
"startYear": "1900",
"endYear": "1930",
"timeZoneDesc": "daweerrewereopreproewropewredfkfdufssfsfsfsfrerewrBlahhhhh..",
"timeZoneID": "1",
"note": {
"notes": [
{
"id": "1",
"title": "Mmm"
},
{
"id": "2",
"title": "Wmm"
},
{
"id": "3",
"title": "Smm"
}
]
},
"links": [
{
"id": "1",
"title": "Red House",
"url": "http://infopedia.nl.sg/articles/SIP_611_2004-12-24.html"
},
{
"id": "2",
"title": "Joo Chiat",
"url": "http://www.the-inncrowd.com/joochiat.htm"
},
{
"id": "3",
"title": "Bake",
"url": "https://thelongnwindingroad.wordpress.com/tag/red-house-bakery"
}
]
}
]
}
}
EDIT:
Here is what you want:
var infoLength= JSON.infos.info.length;
for (infoIndex = 0; infoIndex < infoLength; infoIndex++) {
var notesLength= JSON.infos.info[infoIndex].note.notes.length;
for (noteIndex = 0; noteIndex < notesLength; noteIndex++) {
alert(JSON.infos.info[infoIndex].note.notes[noteIndex].title);
}
}
Putting your json into an var called obj, use the following:
obj.infos.info[0].note.notes[0].title
http://jsfiddle.net/Znq34/
Well the "path" to the JSON notes array-like object is:
json.infos.info[0].note.notes;
So you could do something like:
var notes = json.infos.info[0].note.notes;
var titles = [];
for (var i = 0, len = notes.length; i < len; i++)
{
titles.push(notes[i].title);
}
alert('titles is: ' + titles.join(', '));
Fiddle: http://jsfiddle.net/garreh/uDxqD/
Are you using jQuery? ;-)
// Assuming your using "success" in ajax response
success: function(json)
{
var titles = $(json.infos.info[0].note.notes).map(function() {
return this.title;
}).get();
alert(titles.join(', '));
}
First count the length of notes
var len = jsonobject.infos.info.note.notes.length;
Then loops through and get
var title = jsonobject.infos.info.note.notes[i].title;

Categories