I am creating a dictionary app in React, I have loaded in the JSON dictionary which looks like this:
{
"DIPLOBLASTIC": "Characterizing the ovum when it has two primary germinallayers.",
"DEFIGURE": "To delineate. [Obs.]These two stones as they are here defigured. Weever.",
"LOMBARD": "Of or pertaining to Lombardy, or the inhabitants of Lombardy.",
"BAHAISM": "The religious tenets or practices of the Bahais.",
"FUMERELL": "See Femerell."
}
The user enters a word in the input field and the value is then passed into the following function to search for a matching key in the JSON. Matching words are then pushed into an array of results with their respective value.
handleSearch: function(term) {
var term = term;
var results = [];
for (var key in Dictionary) {
if (Dictionary.hasOwnProperty(key)) {
if (term == Dictionary[key]) {
results.push(Dictionary[key])
}
}
}
console.log(results)
},
However I am struggling to find a successful way of looping through it to get results. the console is logging an empty array.
Can anyone please suggest where I am going wrong?
You can have better matching by adding a compare function (in example below it is the compareTerm function). What I did there is comparing if the term STARTS with the dictionary key, if you want it to be any part of the string you can change it from === 0 to > -1.
// compare function which needs to be added somewhere
function compareTerm(term, compareTo) {
var shortenedCompareTo = compareTo
.split('')
.slice(0, term.length)
.join('');
return term.indexOf(shortenedCompareTo.toLowerCase()) === 0;
}
// only changed the compare function
handleSearch: function(term) {
var results = [];
for (var key in Dictionary) {
if (Dictionary.hasOwnProperty(key)) {
if (compareTerm(term, Dictionary[key])) {
results.push(Dictionary[key])
}
}
}
console.log(results);
},
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 12 months ago.
Improve this question
i have a json with structure like this
{
"india": {
"north_states": ["TN", "AP", "MP", "AB"],
"south_states": ["PB", "UP", "RJ", "HR"]
},
"us": {
"north_states": ["AC", "AD", "AE", "AF"],
"south_states": ["BA", "BB", "BC", "BD"]
},
}
Now if I search for "UP", I have to get south_states and india as reply. how do i do that in JavaScript?
For example:
I need to get the country name based upon the input given in search. for example if i get the input value as 'UP' i need to search the json where UP is and get its key (south_states) and i also need to get the country name as india. the result should take the input of state acronym name and give both the keys as country name and the state_location(south or north)
Parse the JSON into a JS object that you can loop over.
Loop over the main object properties, and then loop over each of those object's properties, and if any of those arrays includes the value you want to match, return the key of the main object, and the key of the inner object.
const json = '{"india":{"north_states":["TN","AP","MP","AB"],"south_states":["PB","UP","RJ","HR"]},"us":{"north_states":["AC","AD","AE","AF"],"south_states":["BA","BB","BC","BD"]}}';
const data = JSON.parse(json);
function check(data, val) {
for (let key in data) {
for (let innerkey in data[key]) {
if (data[key][innerkey].includes(val)) {
return [key, innerkey];
}
}
}
return 'No match';
}
console.log(check(data, 'UP'));
console.log(check(data, 'BO'));
console.log(check(data, 'AF'));
I would iterate in this fashion:
the code might need some tweaking, but it works.
this uses recursion, to iterate the JSON to find the objects/array's that match. If the structure of the JSON is fixed, it could be even easier.
const countries = { "india":{"north_states":["TN","AP","MP","AB"],"south_states":["PB","UP","RJ","HR"]}, "us":{"north_states":["AC","AD","AE","AF"],"south_states":["BA","BB","BC","BD"]}, };
function findItems(data, value, pkey){
let results = [];
for(let key of Object.keys(data)){
let newData = data[key];
if(typeof(newData) == 'string'){
if(newData == value){
results.push(pkey);
}
} else {
results = findItems(newData, value, key).concat(results);
}
}
if(results.length > 0 && pkey && results.indexOf(pkey) == -1){
results.push(pkey);
}
return results;
}
let search = findItems(countries, 'UP');
console.info(search);
For a fixed structure, and only on result should be found:
const countries = { "india":{"north_states":["TN","AP","MP","AB"],"south_states":["PB","UP","RJ","HR"]}, "us":{"north_states":["AC","AD","AE","AF"],"south_states":["BA","BB","BC","BD"]}, };
function findItems(data, searchTerm){
let results = [];
for(let country of Object.keys(data)){
let stateGroups = data[country];
for(let stateGroupName of Object.keys(stateGroups)){
let stateGroup = stateGroups[stateGroupName];
if(stateGroup.indexOf(searchTerm)!=-1){
return [country, stateGroupName];
}
}
}
}
let search = findItems(countries, 'UP');
console.info(search);
i have following problem:
I parse a CSV file and then the data should automatically get uploaded to a MySQL database. Now the problem is that i have the datatypes "varchar" or "decimal". Here at stackoverflow I have already gotten help that if the data type is "decimal" then there stand only the number in the records.
The records (rec) look like this:
[ { examplename1: 'example1',
examplename2: 'example2',
examplename3: 'example3',
examplename4: 'example4',
examplename5: 'example5',
examplename6: 'example6',
examplename7: 'example7',
examplename8: 'example8',
examplename9: 'example9',
examplename10: 'example10',
examplename11: 'example11',
examplename12: 'example12',
Diff_In_Hauswaehrung: -103600,
examplename14: 'example14',
Marktwert_NPV: -111146.16,
examplename16: 'example16' },
{ examplename1: 'example1',
examplename2: 'example2',
examplename3: 'example3',
examplename4: 'example4',
examplename5: 'example5',
examplename6: 'example6',
examplename7: 'example7',
examplename8: 'example8',
examplename9: 'example9',
examplename10: 'example10',
examplename11: 'example11',
examplename12: 'example12',
Diff_In_Hauswaehrung: 53851.33,
examplename14: 'example14',
Marktwert_NPV: 47328.16,
examplename16: 'example16' } ]
You can see that in "Diff_In_Hauswaehrung" and "Marktwert_NPV" there stand a number without ''.
These are also displayed in yellow in the console.
Now i want to check if there is such a number or only a string with '' and if there is a number then i want no "" around this value in the SQL Query.
Now i have a forEach loop where all values are uploaded with ""... but no distinction takes place... keysY are only the keys of the rec.
rec.forEach(entry => {
values = `"${entry[keysY[0]]}"`
for (var i = 1; i < keysY.length; i++) {
values += `,"${entry[keysY[i]]}"`
}
//console.log(values)
var sql = `INSERT INTO ${richtigername} (${namen}) VALUES (${values})`;
connection.query(sql, [values], (error, response) => {
console.log(error || response);
I hope you can help me :)
Best regards,
Frederic
To check if a value contains a valid number cast it to a Number. If the value is not a number the result of that cast is false, otherwise it's number. Next, check if the result is (not) a number using isNaN. If the result is false it is a number. To simplify this add a ! beforehand to negate the final result.
Here's an example:
!isNaN(Number("12.2"))
// returns true (valid number)
!isNaN(Number("asdf12"))
// returns false (no valid number)
!isNaN(Number(12))
// returns true (valid number)
So in your case this should do the trick:
for (var i = 1; i < keysY.length; i++) {
if(!isNaN(Number(${entry[keysY[i]]}) {
// it's a number, no quotes:
values += `,${entry[keysY[i]]}`;
} else {
// it's not a number (NaN) add quotes:
values += `,"${entry[keysY[i]]}"`;
}
}
thanks :) but i have empty columns and I solve it with typeof because then the empty columns are "strings".. with isNaN(Number() also empty columns are displayed as "false" but must be "true" or only with Number() empty columns are not NaN..
rec.forEach(entry => {
if (typeof entry[keysY[0]] == "string") {
values = `"${entry[keysY[0]]}"`
} else {
values = entry[keysY[0]]
}
for (var i = 1; i < keysY.length; i++) {
if (typeof entry[keysY[i]] == "string") {
values += `,"${entry[keysY[i]]}"`;
} else {
values += `,${entry[keysY[i]]}`;
}
the $ and ` are only needed if i want something like to put this in quotation marks or to put a comma in front of.
I have pouchdb/couchbase data with equipment that has user assigned to them.
Equipment with _id and in the equipment doc there is a checkedOutBy with the user._id as the value. Within the employee object there is user.name. When I get the equipment objects how do I also get the user.name and display with the equipment.
I have searched and read about map/reduce that uses emit and do not grasp the idea. My code that i wrote from what i learned is:
by the way I am also using Angularjs.
field = "eq::"
this.getAllEquip = function(field){
function map(doc) {
if (doc.checkedOutBy !== undefined) {
emit(doc.checkedOutBy, {empName : doc.name});
}
}
var result = database.query(map, {include_docs: true,
attachments: true,
startkey: field,
endkey: field + '\uffff'})
.catch(function (err) {
//error stuff here
});
return result
};
I don't see where the two docs would get together. What am i missing? My result is empty.
The equipment json looks like:
{checkedOutBy: "us::10015", description: "3P Microsoft Surface w/stylus & power cord", equipId: "SUR1501", purchaseDate: "", rCost: 1000, id:"eq::10001"}
Emlpoyee json:
{"firstname":"Joe","gender":"male","lastname":"Blow","status":"active","title":"office","type":"userInfo","_id":"us::10015","_rev":"2-95e9f34784094104ad24bbf2894ae786"}
Thank you for your help.
Something like this should work, if I understood the question correctly:
//Sample Array of Objects with Equipment
var arr1=[{checkedout:"abc1",desc:"item1",id:1},
{checkedout:"abc2",desc:"item2",id:2},
{checkedout:"abc3",desc:"item3",id:3},
{checkedout:"abc1",desc:"item1",id:4},
{checkedout:"abc4",desc:"item3",id:5},
{checkedout:"abc6",desc:"item3",id:6}];
//Sample array of objects with Employee - the "id" in arr2 matches with "checkout" in arr1
var arr2=[{name:"john",id:"abc1"},
{name:"jack",id:"abc2"},
{name:"alice",id:"abc3"},
{name:"james",id:"abc4"}];
var result = []; //final result array
//loop through equipment array arr1
arr1.forEach(function(obj) {
var tempObj = obj;
var checkedout_id=obj.checkedout;
//do array.find which will return the first element in the array which satisfies the given function. This is absed on the assumption that that the id is unique for employee and there wont bwe multiple employees with same id (which is the "checkedout" field in equipment. If the employee is not found, it will return undefined.
var foundname = arr2.find(function(obj) {
if (obj.id == checkedout_id)
return obj.name
})
//Create the object to be inserted into the final array by adding a new key called "name", based on the result of above find function
if (foundname != undefined) {
tempObj.name=foundname.name
}
else {
tempObj.name = "Not found";
}
result.push(tempObj);
})
This is my Pouchdb solution, thank you Vijay for leading me to this solution.
First I get all my equipment. Then I use Vijay's idea to loop through the array and add the name to the object and build new array. I found there is a need to go into the .doc. part of the object as in obj.doc.checkedOutBy and tempObj.doc.name to get the job done.
$pouchDB.getAllDocs('eq::').then(function(udata){
var result = [];
//loop through equipment array
udata.rows.forEach(function(obj) {
var tempObj = obj;
var checkedout_id=obj.doc.checkedOutBy;
if (checkedout_id != undefined) {
$pouchDB.get(checkedout_id).then(function(emp){
return emp.firstname + " " + emp.lastname
}).then(function(name){
tempObj.doc.name = name;
});
}
result.push(tempObj);
})
in my service I have:
this.get = function(documentId) {
return database.get(documentId);
};
and:
this.getAllDocs = function(field){
return database.allDocs({
include_docs: true,
attachments: true,
startkey: field,
endkey: field + '\uffff'});
};
I am attempting to extract JSON values (from structure called jsonWithListOfStatesAndCounters) if it matches with an element in my inputted array (inputedJurisdictionArray). My inputed array contains sting values that include singular or multiple state names (i.e. var inputedJurisdictionArray = ["Iowa", "California, Indiana, Delaware", "Florida"]). The singular State values in this array are handled normally at the end, but the multiple state values is where it gets tricky. I am using split() in order to turn them into another array so they can get processed one by one. Anytime one of the states from this inputed array matches with a "state" value in jsonWithListOfStatesAndCounters, I am extracting it into another JSON structure and pushing it at the end of every block into my initial variable myJurisdictionJSON. The problem I am having is that once these forEach loops are completed, I am still left with my original values in myJurisdictionJSON, instead of the val and counter that should be extracted. The jsonWithListOfStatesAndCounters definitely contains the values that should match with the elements of my inputedJurisdictionArray, but the information is not being pushed into myJurisdictionJSON. What am I doing wrong? Any tips/pointers will be helpful.
var myJurisdictionJSON = [{
jurisdiction_val: 'jurisdiction_val',
jurisdiction_counter: 'jurisdiction_counter'
}];
inputedJurisdictionArray.forEach(function each(item) {
if (Array.isArray(item)) {
item.forEach(each);
} else {
var jurisdictionInput = item;
jsonWithListOfStatesAndCounters.forEach(function each(item) {
if (Array.isArray(item)) {
item.forEach(each);
} else {
if (jurisdictionInput.includes(",") === true){//Checking if more than one jurisdiction in string
var jurisdictionArr = jurisdictionInput.split(", ");
var jurisdictionCounter = item.jurisdictionCounter;
var jurisdictionState = item.jurisdictionState;
jurisdictionArr.forEach(function(element) {
if (myJurisdictionJSON.jurisdiction_counter == 'jurisdiction_counter'){ // If nothing is pushed into our predefined JSON object
if (jurisdictionState.toLowerCase() == trim(element.toLowerCase())) {
var jurisdictionJSON_inner = {
jurisdiction_val: element,
jurisdiction_counter: jurisdictionCounter
};
myJurisdictionJSON.push(jurisdictionJSON_inner);
return;
}
}else if (myJurisdictionJSON.jurisdiction_counter != 'jurisdiction_counter'){ // if an item has been pushed into myJurisdictionJSON, append the next items
var jurisdictionCounter = item.jurisdictionCounter;
var jurisdictionState = item.jurisdictionState;
if (jurisdictionState.toLowerCase() == trim(jurisdictionInput.toLowerCase())) {
jurisdictionJSON_inner.jurisdiction_val = jurisdictionJSON_inner.jurisdiction_val + ", " + jurisdictionInput;
jurisdictionJSON_inner.jurisdiction_counter = jurisdictionJSON_inner.jurisdiction_counter + ", " + jurisdictionCounter;
myJurisdictionJSON.push(jurisdictionJSON_inner);
return;
}
}
});
}
else{// if only one jurisdiction state in jurisdictionInput string
var jurisdictionCounter = item.jurisdictionCounter;
var jurisdictionState = item.jurisdictionState;
if (jurisdictionState.toLowerCase() == trim(jurisdictionInput.toLowerCase())) {
var jurisdictionJSON_inner = {
jurisdiction_val: jurisdictionInput,
jurisdiction_counter: jurisdictionCounter
};
myJurisdictionJSON.push(jurisdictionJSON_inner);
return;
}
}
}
});
I'm not totally sure the output is what you want but it's close.
// input data as per your example
let inputedJurisdictionArray = [
'Iowa',
'California, Indiana, Delaware',
'Florida'
];
// I had to make this part up. It's missing from the example
let jsonWithListOfStatesAndCounters = [{
jurisdictionCounter: 2,
jurisdictionState: 'Florida'
},
{
jurisdictionCounter: 4,
jurisdictionState: 'Indiana'
},
{
jurisdictionCounter: 3,
jurisdictionState: 'Texas'
}
];
// first, fix up inputedJurisdictionArray
// reduce() loops over each array element
// in this case we're actually returning a LARGER
// array instead of a reduced on but this method works
// There's a few things going on here. We split, the current element
// on the ','. Taht gives us an array. We call map() on it.
// this also loops over each value of the array and returns an
// array of the same length. So on each loop, trim() the whitespace
// Then make the accumulator concatenate the current array.
// Fat arrow ( => ) functions return the results when it's one statement.
inputedJurisdictionArray = inputedJurisdictionArray.reduce(
(acc, curr) => acc.concat(curr.split(',').map(el => el.trim())), []
);
// now we can filter() jsonWithListOfStatesAndCounters. Loop through
// each element. If its jurisdictionState property happens to be in
// the inputedJurisdictionArray array, then add it to the
// myJurisdictionJSON array.
let myJurisdictionJSON = jsonWithListOfStatesAndCounters.filter(el =>
inputedJurisdictionArray['includes'](el.jurisdictionState)
);
console.log(myJurisdictionJSON);
I've been trying to 'correlate' between user picked answers and an object property name so that if the two matches then it will display what is inside.
My program is a recipe finder that gives back a recipe that consists of the ingredients the user picked.
my code currently looks like:
//property are the ingredients and the value are the recipes that contain those ingredients. The map is automatically generated
``var map = {
"pork" : [recipe1, recipe2, ...],
"beef" : [],
"chicken" :[],
}
//this gets the user pick from the dom
var cucumber = specificVegetable[7];
var lemon = specificFruits[0];
//Then this code finds the intersection of the recipe(recipes that use more than one ingredients)
function intersect(array1, array2)
{
return array1.filter(function(n) {
return array2.indexOf(n) != -1
});
}
var recipiesWithLemon = map["lemon"]; **// makes the lemon object is map**
var recipiesWithCucumber = map["cucumber"]; **// makes the cucumber object in map**
//Here is where I am stuck
function check(){
var both = intersect(recipiesWithLemon, recipiesWithCucumber);
if ( cucumber.checked && lemon.checked){
for (var stuff in map){
if(stuff="cucumber" && stuff="lemon"){
return both;
}
}
}
}
check();
so basically what I tried to do was I made my intersect and then if user pick is lemon and cucumber then look at the properties in the map object. if the name of the property equals to the exact string then return both. That was the plan but the code does not work and I'm not sure how to fix it.
My plan is to write code for every possible outcome the user may makes so I need to find the correlation between the user pick and the map which stores the recipe. I realize this is not the most effective way but I'm stumped on how to do it another way.
Thanks for the help.
Im using the open source project jinqJs to simplify the process.
I also changed your map to an array of JSON objects. If you must have the map object not as an array, let me know. I will change the sample code.
var map = [
{"pork" : ['recipe1', 'recipe2']},
{"beef" : ['recipe3', 'recipe4']},
{"peach" :['recipe5', 'recipe6']},
{"carrot" :['recipe7', 'recipe8']}
];
var selectedFruit = 'peach';
var selectedVeggie = 'carrot';
var selections = [selectedFruit, selectedVeggie];
var result = jinqJs().from(map).where(function(row){
for(var f in row) {
if (selections.indexOf(f) > -1)
return true;
}
return false;
}).select();
document.body.innerHTML += '<pre>' + JSON.stringify(result, null, 2) + '</pre><br><br>';
<script src="https://rawgit.com/fordth/jinqJs/master/jinqjs.js"></script>