JS - conditional property selection - javascript

I have two arrays with the following structure:
First dictionary:
[{id: 111, abbr: "FBI", name: "Federal Burreau of Investigation"},
{id: 59, abbr: "CIA", name: "Central Intelligence Agency"},
{id: 130, abbr: "EU", name: "European Union"}]
Second dictionary:
[{id: 28, name: "Administration"},
{id: 107, name: "Advocacy"},
{id: 100, name: "Agriculture"},
{id: 77, name: "Air & Aviation"}]
I am trying to create a delimiter function that accesses these objects in the following way:
finalDictionary.push({ delimiter: dictionary[0].abbr.charAt(0) });
and correspondingly:
finalDictionary.push({ delimiter: dictionary[i].name.charAt(0) });
My aim is to make the method universal and diminish the amount of final code. As you see, the only difference here is the property by which I am accessing the dictionary, 'abbr' and 'name'. I tried to do it the following way:
var ext = (name === 'agencies') ? 'abbr' : 'name';
finalDictionary.push({ delimiter: dictionary[i].ext.charAt(0) });
However, I get an error:
TypeError: Cannot read property 'charAt' of undefined
The question is how can I conditionally access the object property? Maybe, there is a better approach than this one? If not, what am I doing wrong?

The problem is in this line:
dictionary[i].ext.charAt(0)
dictionary[i].ext assume that you have a property ext inside dictionary[i] which you don't and therefore it returns undefined.
than what happens is undefined.charAt(0) which raises your error
Change it to:
dictionary[i][ext].charAt(0)
Than the property here is the value of ext which is 'abbr' or 'name'

There is no property named ext in the example json you have shown, that is why you are facing this error.

Related

Jquery TokenInput Initial Strings Search

Im using jquery Tokeninput library for autocomplete functionality. Im currently struggling with the issue I have with the search results. When I type something, it returns all the words for characters which are being typed. I want it to only return the search results where initial strings match.
For example, if I type "Na", it returns all the words which have "Na" such as "Canada", "Financial" etc.
I would ONLY like for it to return words which start with "Na" such as "Nation", "Nascar" etc.
Im new to JavaScript to facing trouble updating this script. Can someone please help ?
Here is the library that Im using - https://github.com/loopj/jquery-tokeninput/blob/master/src/jquery.tokeninput.js
$("#demo-input").tokenInput([
{id: 7, name: "Canada"},
{id: 11, name: "Financial "},
{id: 13, name: "Nation"},
{id: 17, name: "Nascar"},
{id: 19, name: "USA"},
{id: 31, name: "Economics"}
]);
I checked library code and I don't think you can pass any option to change default search type which checks for existence of search query within a value. However, I found a heck which you could use (IMO you shouldn't unless necessary).
Working example here
Library allows you to process search results by using onResult and onCachedResult callbacks you could use that for your leverage.
$("#demo-input").tokenInput([
{id: 7, name: "Canada"},
{id: 11, name: "Financial "},
{id: 13, name: "Nation"},
{id: 17, name: "Nascar"},
{id: 19, name: "USA"},
{id: 31, name: "Economics"}
],
{
onResult: filterSearchResults,
onCachedResult: filterSearchResults
});
function filterSearchResults(items){
var query = $("#demo-input").parent().find("ul li input").val().toLowerCase();
return items.filter(i => i.name.toLowerCase().startsWith(query));
}

Populating a react-table with an object instead of a list

The documentation for the react-table library (https://github.com/react-tools/react-table#data) states:
"Simply pass the data prop anything that resembles an array or object."
However, the tables are rendered as expected when passing in an array of data, but when passing an object, I get the error:
"Invalid prop data of type object supplied to ReactTable, expected array."
An example data object looks like this:
const data = {
"entry1": {
name: 'Tanner Linsley',
age: 26,
friend: {
name: 'Jason Maurer',
age: 23,
}
}, "entry2": {
name: 'aTanner Linsley',
age: 26,
friend: {
name: 'aJason Maurer',
age: 23,
}
} };
Is this a problem with the structure of my object, or does it simply mean the library does not support the population via objects in this way?
Note: I prefer to maintain this data structure (which will become huge) as an object (dictionary) instead of an array so I can efficiently access elements by key for another use (outside of react-table).
The react-table library would expect an input like that:
const data = [{
name: 'Tanner Linsley',
age: 26,
friend: {
name: 'Jason Maurer',
age: 23,
}
},{
name: 'aTanner Linsley',
age: 26,
friend: {
name: 'aJason Maurer',
age: 23,
}
}];
I prefer to maintain this data structure
Is there any particular reason to that? However, if you really want to do it like that, you could apply the Object.values(...) (MDN Source) method to your data before passing it to the component. In that case you can manage it as you desire and the component will get the right data structure.
const convertedObject = Object.values(data);
But keep in mind that in this case, you will lose your keys entry1 and so on.

Loop through an array of objects and get where object.field equals value

I'm currently working on a small application where I have to loop through an enormous array of objects. What would be the most efficient method to perform this?
var array = [
{
id: "1",
name: "Alpha"
},
{
id: "2",
name: "Beta"
},
...
];
I'd like to get each object where name equals "Alpha". I'm currently using a simple if statement to filter the objects with a different name value out, but I wonder if there's a more efficient way to do this, performance-wise.
It's worth to mention that I'll push the matching results into a new array.
No, there is no more efficient way.
The alternative is to build and maintain some kind of internal data structure which allows you to find the desired elements faster. As usual, the trade off is between the work involved in maintaining such a structure vs the time it saves you.
I don't have any way about which I would know it's more effective.
But if you had your objects ordered by name you could stop your search imideatly upon reaching an object whose name is not equal to "Alpha".
To find the first object you're looking for you can use binary search and from this Object you go up and down until at both ends you reach an object which isn't named "Alpha" or the end of array.
This is only a way of optimizing and will require time to sort the array and also will take more time when adding an element.
There's a JavaScript function exactly for this kind of task. Filter
From the Docs
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
Here is a small example by code for getting all element from array which has a certain 'name' field:
const arr = [
{name: 'Abc'},
{name: 'Xyz'},
{name: 'Lmn'},
{name: 'Xyz'},
{name: 'Xyz'}
];
let response = findByName('Xyz');
console.log(response);
function findByName (name) {
return arr.filter((element) => {
return element.name = name;
});
}
If you need more than one time a collection with a given name, you could use an object with the names as hashes and have instantly access to the items.
var array = [{ id: "1", name: "Alpha" }, { id: "2", name: "Beta" }, { id: "3", name: "Beta" }, { id: "4", name: "Gamma" }, { id: "5", name: "Beta" }, { id: "2", name: "Alpha" }],
hash = Object.create(null);
array.forEach(function (a) {
if (!hash[a.name]) {
hash[a.name] = [];
}
hash[a.name].push(a);
});
console.log(hash);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Test whether value exists within array of objects

I have an array of objects and I would like to test it to determine whether a property with a certain value exists (at least one occurrence) and for it to return a boolean value to indicate the result. I'm using the Ramda library and have been experimenting with the has function to try and achieve this, however this only returns a boolean on whether the actual property exists and not it's respective value.
const data = [
{
id: 10004,
name: 'Daniel',
age: 43,
sport: 'football'
},
{
id: 10005,
name: 'Tom',
age: 23,
sport: 'rugby'
},
{
id: 10006,
name: 'Lewis',
age: 32,
sport: 'football'
},
];
Checking the array of objects for sport: 'rugby' should return true and sport: 'tennis' should return false.
Any help will be greatly appreciated, thanks.
If you're looking for a Ramda solution, this would do fine:
R.filter(R.propEq('sport', 'rugby'))(data)
R.has, as you noted, just checks whether an object has the named property. R.propIs checks whether the property is of the given type. R.propEq tests whether the property exists and equals a given value, and the more generic R.propSatisfies checks whether the property value matches an arbitrary predicate.
You can try this function:
function myFind(data, key, value) {
return data.some(function(obj){
return key in obj && obj[key] == value;
});
}
Reference: Array.some()

Access object property

How i can select the count(user) from the tab object?
var tab =
[
{ id: '1', 'count(user)': 11 },
{ id: '2', 'count(user)': 31 },
{ id: '3', 'count(user)': 3 }
]
This prints 2:
console.log(tab[1].id)
but this gives me an error:
console.log(tab[1].count(user))
ReferenceError: user is not defined
How can I fix this?
Like this:
alert(tab[1]["count(user)"]);
Here is an example: JSFiddle
By the way, while the JSON in your example technically works, it is not formatted in a "best practice" way. Parameter names should have quotes around them:
{ 'id': '1',...
And parameter names should be valid JavaScript variables names, ie., no parenthesis, brackets, etc. This would be a more acceptable name:
'count_user': 11
Then you would not have had an issue using
console.log(tab[1].count_user)

Categories