So I am dealing with an object that looks a bit like this:
{
examples: [
{ key: 'value1' },
{ key: 'value1' },
{ key: 'value1' },
{ key: 'value2' },
{ key: 'value2' },
{ key: 'value2' }
]
}
As you can see the values are ordered. I'm trying to get where the value is value2 and I'm sure there is a more efficient way than what I am doing currently, as the actual object is significantly larger and so it takes some time to reach value2.
This is the function I created:
function getValue2 (obj, num) {
if (obj.examples[num] = "value2"){
console.log(obj.examples[num]);
}
else {
getValue2(obj, num + 1);
};
};
var x = JSON.parse(obj);
getValue2(x, 0);
Thank you in advance! :)
You can use Array#find:
returns the value of the first element in the provided array that satisfies the provided testing function. If no values satisfy the testing function, undefined is returned.
const data = {
examples: [ { key: 'value1' }, { key: 'value1' }, { key: 'value1' }, { key: 'value2' }, { key: 'value2' }, { key: 'value2' } ]
};
const res = data.examples.find(({ key }) => key === 'value2');
console.log(res);
To get the index of the first occurrence, you can use Array#findIndex:
returns the index of the first element in the array that satisfies the provided testing function. Otherwise, it returns -1, indicating that no element passed the test.
const data = {
examples: [ { key: 'value1' }, { key: 'value1' }, { key: 'value1' }, { key: 'value2' }, { key: 'value2' }, { key: 'value2' } ]
};
const index = data.examples.findIndex(({ key }) => key === 'value2');
console.log(index);
How about using Object.values, like this:
function getValue2(obj){
return Object.values(obj.examples).find(e => e === 'value2')
}
The first problem I see is you are using a single equals = to check equality when it should be == or ===.
As for alternative ways to run a similar function, I suggest you look up and learn about the for and while loops, as they are essential for JS.
Related
This question already has answers here:
How to convert an array into an object in javascript with mapped key-value pairs?
(4 answers)
Closed 1 year ago.
In my code I make a SELECT on an SQL table where parameters are stored and I would like to output an OBJECT in this way:
{
inscription_max: 0,
inscription_open: false,
liste_attente_max: 0
}
SQL Return :
[
RowDataPacket { setting: 'inscription_max', value: '0' },
RowDataPacket { setting: 'inscription_open', value: 'false' },
RowDataPacket { setting: 'liste_attente_max', value: '0' }
]
If you need more information, don't hesitate.
I hope you can help me.
Thank you in advance.
You can try reduce for an array that will add a new field to resulting object for every array element : smth like this
let data = [
{ setting: 'inscription_max', value: '0' },
{ setting: 'inscription_open', value: 'false' },
{ setting: 'liste_attente_max', value: '0' }
]
data.reduce((acc, rec) => ({...acc, [rec.setting] : rec.value}), {})
You can .map() each object to a variant of the current object, where the setting value is the key of the new object and the value of the value property is the value of the new object. You can also use JSON.parse(value) to ensure its string version is parsed to its primitive value (see second example). Then you can use Object.assign() with the spread syntax to build an object from your new array of objects:
const arr = [
{ setting: 'inscription_max', value: '0' },
{ setting: 'inscription_open', value: 'false' },
{ setting: 'liste_attente_max', value: '0' }
];
const res = Object.assign({}, ...arr.map(({setting, value}) => ({[setting]: value})));
console.log(res);
If you can support Object.fromEntries(), the same result can be achieved with a little less code:
const arr = [
{ setting: 'inscription_max', value: '0' },
{ setting: 'inscription_open', value: 'false' },
{ setting: 'liste_attente_max', value: '0' }
];
const res = Object.fromEntries(arr.map(({setting, value}) => [setting, JSON.parse(value)]));
console.log(res);
The above can be written more elegantly, as pointed out by #Andreas:
const arr = [ { setting: 'inscription_max', value: '0' }, { setting: 'inscription_open', value: 'false' }, { setting: 'liste_attente_max', value: '0' } ];
const res = Object.fromEntries(arr.map(Object.values)); // credit to: #Andreas
console.log(res);
I'm trying to implement a custom filter after using Angular's inbuilt Key Value pipe
I have an array with values for example
object= [
{ key: "Added_By", value: "Yi" },
{ key: "Assigned_To", value: "-" },
{ key: "Bought_Date", value: 43810 },
{ key: "Brand", value: "Samsung PM863" },
{ key: "Capacity", value: 3.84 },
]
I want to filter based on multiple incoming values but incoming values vary for example
It Could be 1 key/Value
Filter= [{ key: "Added_By", value: "Yi" }]// Return Object
or multiple
Filter= [{ key: "Added_By", value: "Yi" }, { key: "Bought_Date", value: 43810 }] //both matches return object
Filter= [{ key: "Added_By", value: "ABC" }, { key: "Bought_Date", value: 43810 }] //1 match but 1 doesn't return false
I want to return object if all the conditions are met
For a single key/value I tried
let Key= Filter[0].key
let Value=Filter[0].value
let KeyFilter = object.filter(x => x.key === Key)
if (KeyFilter[0].value.toString().toLowerCase().indexOf(Value.toLowerCase()) !== -1)
return items
But this approach only works only when 1 object is present in filter array
I've created a function that accepts an array of objects, and an object with key: value pairs.
The keys of objects in the array must match with object keys to work.
I always use it when I need to filter an array based on various conditions.
export const filterArray = (filterData, toBeFiltered) => {
return toBeFiltered.filter(item => {
for (const key in filterData) {
if (item[key] === null || item[key] === undefined) {
return false;
} else {
if (typeof filterData[key] === 'string') {
if (!(item[key]).toLowerCase().includes((filterData[key].trim()).toLowerCase())) {
return false;
}
} else if (item[key] !== filterData[key]) {
return false;
}
}
}
return true;
});
};
Hope it helps.
In the below array, I have objects with key/value pairs
var options = [{
key: "select",
value: null
}, {
key: "one",
value: "First Option"
},
{
key: "second",
value: "Second Option"
}];
how to get the value based on key from options array?
For example, if the key is "select" it should return null,
if the key is "one" it should return "First Option".
ES6 has the find-function for arrays:
var val = options.find(function(o){ return o.key==="select" }).value;
And maybe wrap it in a function of your own to make it a bit more reusable:
function findValue(arr, key){
return arr.find(function(o){ return o.key===key }).value;
}
var val = findValue(options,"select");
I would argue this is the most semantically correct answer without modifying the original array, but you must have realized by now that there are many ways to skin this cat. (I like Zodiac Zubeda's answer because it's a simple for-loop so fast and backwards compatible and has the break that skips unnecessary iterations.)
You can search for the object you want from the array, then get the value of that object:
var value;
// Loop through the options array
for (var i = 0; i < options.length; i++) {
// If the key for this iteration's element is desired
if (options[i].key == "select") {
// Set the value to appropriately and exit the loop
value = options[i].value;
break;
}
}
This code makes "value" equal to the value you want, based on your key. If you want to determine the value multiple times, you can wrap the code in a function and return value. You'd probably also want to add a parameter for the desired key, and replace options[i].key == "select" with "options[i].key == <parameter name>".
Alternatively, you can structure your objects like so:
var options = {
"select": null,
"one": "First Option",
"second": "Second Option"
};
With this, you can access the value of a desired key like so:
options[<desired key>]
So, options["select"] would return null.
Using Array.prototype.filter (modern browsers and IE9+):
options.filter(function(opt) {
return opt.key === 'one';
})[0].value;
Or a one-liner using ES6 arrow notation:
options.filter(opt => opt.key === 'one')[0].value;
Reusable function, returning null if a match is not found:
function findValueByKey(opts, key) {
var match = opts.filter(function(opt) {
return opt.key === key;
});
return match[0] ? match[0].value : null;
}
JSFiddle: https://jsfiddle.net/02oawajt/3/
You have to brute force it...
function findValueForOption(key) {
for (i = 0; i < options.length; i++) {
if (options[i].key === key) {
return options[i].value;
}
}
return null; // Or do whatever you feel is appropriate when an unspecified key is requested...
}
Arraymap use to find key and value
var options = [{
key: "select",
value: null
}, {
key: "one",
value: "First Option"
},
{
key: "second",
value: "Second Option"
}];
var run = options.map(function (item,index) {
var fullname = 'the key='+item.key+',and value='+item.value;
return fullname;
})
console.log(run);
var options = [{
key: "select",
value: null
}, {
key: "one",
value: "First Option"
}, {
key: "second",
value: "Second Option"
}];
// output values of whatever you like
checkValue("select");
console.log("------------------------------");
checkValue("one");
console.log("------------------------------");
checkValue("second");
console.log("------------------------------");
function checkValue(val) {
for (var i = 0; i < options.length; i++) {
if(options[i].key == val){
console.log("VALUE IS: " + options[i].value);
}
}
}
Use forEach to loop through he json..
There are multiple ways of doing it.
This is one of the way
var options = [{
key: "select",
value: null
}, {
key: "one",
value: "First Option"
},
{
key: "second",
value: "Second Option"
}];
options.forEach(function(item){
console.log(item.value)
})
DEMO
You may want to consider restructuring your data. It appears you took key, value literally:
If you structure your data like this:
var options = [
{
select: null
},
{
one: 'first option'
}
];
You can just call options.select to retrieve the value.
If you don't mind the dependency, you can turn your array into a proper Object using Lodash _.fromPairs:
pairs = options.map(o => [o.key, o.value])
// [["select", null], ["one", "First"], ["two", "Second"]]
_.fromPairs(pairs)
// { select: null, one: "First", second: "Second" }
I hope this will work for you
function getValue(keyName) {
if(!keyName) return ''
var value = _.find(options, function(obj){
if(obj.key === keyName) {
return true
}
})
if(value === undefined) return ''
return value.value
}
var a = getValue('one')
Check snippet for working example.
$(function(){
var options = [{
key: "select",
value: null
}, {
key: "one",
value: "First Option"
},
{
key: "second",
value: "Second Option"
}];
function getValue(keyName) {
if(!keyName) return ''
var value = _.find(options, function(obj){
if(obj.key === keyName) {
return true
}
})
if(value === undefined) return ''
return value.value
}
var a = getValue('one')
console.log(a)
})
<script src="http://underscorejs.org/underscore.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
For older/ES3 environments:
function find(arr, key) {
for (var i = 0; i < arr.length; i += 1) {
if (arr[i].key === key) {
return arr[i].value;
}
}
}
For newer/ES5 environments:
function find(arr, key) {
return (arr.filter(function(item) { return item.key === key})[0] || {}).value;
}
This is one way of doing it. I have changed the structure of it like other suggested through program and then access the new Structure.
var options = [{
key: "select",
value: null
}, {
key: "one",
value: "First Option"
},
{
key: "second",
value: "Second Option"
}];
function changeStructure(obj){
var newObj = {};
obj.forEach(function(val, index){
newObj[val['key']] = val['value'];
});
return newObj;
}
var newStructure = changeStructure(options);
New Structure :
{
one : "First Option"
second:"Second Option"
select:null
}
Now you can access it using key:
console.log(newStructure['select']); or console.log(newStructure.select)
JS Fiddle
You can use for..of loop.
var options = [{
key: "select",
value: null
}, {
key: "one",
value: "First Option"
}, {
key: "second",
value: "Second Option"
}];
let filter = (array, prop, res = void 0) => {
for (let {key, value} of array) prop === key && (res = value); return res
}
console.log(filter(options, "select"));
console.log(filter(options, "one"));
console.log(filter(options, "second"));
For my current project, I'm working with an API that returns data formatted like this:
{
groups: [
{
items: [
{
points: [
{ name: "name1", ... },
{ name: "name2", ... },
{ name: "name3", ... },
...
],
...
},
...
]
},
...
],
...
};
I'd like to create a pure function, mapValues, that takes in an object in the above format, as well as an object mapping each name to a value, and returns the same structure, but with each point containing the value that corresponds to its name.
For example, calling mapValues(data, { name1: "value1", name2: "value2", name3: "value3" }) should return this:
{
groups: [
{
items: [
{
points: [
{ name: "name1", value: "value1", ... },
{ name: "name2", value: "value2", ... },
{ name: "name3", value: "value3", ... },
...
],
...
},
...
]
},
...
],
...
};
Here's my first pass:
function mapValues(data, values) {
return _.extend({}, data, {
groups: _.map(ui.groups, (group) => {
return _.extend({}, group, {
items: _.map(group.items, (item) => {
return _.extend({}, item, {
points: _.map(item.points, (point) => {
return _.extend({ value: values[point.name] }, point);
})
});
})
});
})
});
}
That works, but there's quite a bit of nesting a duplicate code. For my second attempt, I reached for recursion.
function mapValues(data, values) {
return (function recursiveMap(object, attributes) {
if (attributes.length === 0) { return _.extend({ value: values[object.name] }, object); }
let key = attributes[0];
return _.extend({}, object, {
[key]: _.map(object[key], child => recursiveMap(child, attributes.slice(1)))
});
})(ui, ["groups", "items", "points"]);
}
That works too, but it's difficult to read and not very concise.
Is there a cleaner way to recursively map an object using Lodash? Ideally, I'm looking for a functional approach.
Here's a way you can do it using Object.assign and no fancy functions
var data = <your data here>;
var values = <your mapped values>;
data.groups.items.points.map(p=>
Object.assign(p, {value: values[p.name]})
);
This works because arrays and objects are pass by reference. So any modifications to the values will result in the original being changed.
If you don't want to mutate your original dataset, it requires you to use {} as the first argument (to assign to a new, empty object) and show clear read/write paths for each object.
var newData = Object.assign({}, data,
{groups:
{items:
{points: data.groups.items.points.map(p=>
Object.assign({}, p, {value: values[p.name]})
)}
}
}
);
I know you wanted Lodash, but I had same issue some time ago and I've came up with this JSFiddle I am using great tool created by nervgh. It is very simple yet usefull. You can adjust this function to be pure using Object.assign, accept key parameter and tweak it however you want. You get the idea.
function mapValues(data, values) {
var iterator = new RecursiveIterator(data);
for(let {node} of iterator) {
if(node.hasOwnProperty('name')) {
node.value = values[node.name];
}
}
return data;
}
I got two data structures in different formats.
The first:
{loginRememberMe: false, test: false}
The second:
[
{
Objectname: "loginEmail",
value: "one"
},
{
Objectname: "loginPassword",
value: "two"
}
]
I am trying to convert the first structure to match the format of the second structure and to then merge them.
This needs to be done using JavaScript / jQuery,
In future please show the final structure you need to have. You cannot directly merge an Object with an Array.
var first = {
loginRememberMe: false,
test: false
}
var second = [{
Objectname: "loginEmail",
value: "one"
}, {
Objectname: "loginPassword",
value: "two"
}]
var modifiedArray = addObjectKeysToArray(second, first);
console.log( modifiedArray );
console.log( second );
console.assert(second !== modifiedArray, 'both arrays should be different');
function addObjectKeysToArray(arr, obj) {
// copy the arr so we don't modify the original
var arrCopy = arr.slice(0);
// loop through the object properties
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
// add to the copied array
arrCopy.push({
Objectname: key,
value: obj[key]
});
}
}
return arrCopy;
}
<script src="http://codepen.io/synthet1c/pen/WrQapG.js"></script>
You can use:
myArray.push({
Objectname: Object.keys(myObject)[0],
value: Object.keys(myObject)[1]
})
if you want to get this array:
[
{
Objectname: "loginEmail",
value: "one"
},
{
Objectname: "loginPassword",
value: "two"
},
{
Objectname: "loginRememberMe",
value: "false"
}
]
and your array of objects is called myArray and the object you want to merge into array is called myObject.
Check demo: Fiddle