My array is the following:
let arr = [
{type: "Benzine", active: false},
{type: "Diesel", active: false},
{type: "Electricity", active: false}
]
And I have a function where I want to get value of the property active of that array:
function isChecked(filterName) {
return arr.filter(f => f.type === filterName).map(c => c.active)[0];
}
That works fine, with [0] at the end. Is there any way to show the active property value without [0] at the end?
No, as long as you use filter, there's not.
The [0] is used to get the first result from that filter.
Since you're just returning the value of active, you could use Array.prototype.some, instead:
let arr = [
{type: "Benzine", active: false},
{type: "Diesel", active: false},
{type: "Electricity", active: true}
];
function isChecked(filterName){
// Is there an element in the array that matches the filter AND is active?
return arr.some(f => f.type === filterName && f.active);
}
console.log("Diesel:", isChecked("Diesel"));
console.log("Electricity:", isChecked("Electricity"));
Instead of using filter, you can use find to get the first matching element of an array.
function isChecked(filterName) {
var elem = arr.find(f => f.type === filterName);
return elem ? elem.active : false;
}
Related
I have an array of objects, there is one field in each object could be boolean or a string of array, for instance
myObjects=[{id: "fruit", selected: true}, {id: "veggie", selected: ["tomato", "cucumber", "potato"]}, {id: "diary", selected:[]}]
I would like to filter out the objects that have selected either not empty or true. The result would be:
result=[{id: "fruit", selected: true}, {id: "veggie", selected: ["tomato", "cucumber", "potato"]}]
Here is my code:
for (const object in myObjects) {
if (!object[selected] || (Array.isArray(object[selected] && object[selected].length ===0)) continue
...
}
But objects with selected is empty array won't get filter out. I got a typescript error
Property 'length' does not exist on type 'boolean | string[]'.
Property 'length' does not exist on type 'false'.
Can anyone help?
You can use the filter method on the myObjects array
const res = myObjects.filter((object) => object.selected.length > 0 || object.selected === true )
You could do it with loop for...of
add object to result array only if selected property is boolean and true:
(typeof object.selected === "boolean" && object.selected)
or selected property is an array and have elements:
(Array.isArray(object["selected"]) && object["selected"].length !== 0)
const myObjects = [{
id: "fruit",
selected: true,
},
{
id: "veggie",
selected: ["tomato", "cucumber", "potato"],
},
{
id: "diary",
selected: [],
},
];
let result = [];
// vv replace 'in' with 'of' since you loop over an array not an object
for (const object of myObjects) {
if (
(typeof object.selected === "boolean" && object.selected) ||
(Array.isArray(object["selected"]) && object["selected"].length !== 0)
)
result.push(object);
}
console.log(result);
I have this simple function, and I am just trying to get the length of this array of objects. For instance I want to return 3 in that case below. I could use .length() but I want to explore more with the reduce method.
function getSum(data) {
const totalNum = data.reduce((sum, a) => sum + a.id, 0);
return totalNum
}
console.log(getSum([
{id: 'ddd6929eac', isComplete: true},
{id: 'a1dd9fbd0', isComplete: true},
{id: 'afa8ee064', isComplete: false}
]))
Thank you very much :)
Well the equivalent of data.length would be:
data.reduce(sum => sum + 1, 0);
But I don't see why you would do that unless you're trying to exclude blank values.
You could add one for each item in the array.
function getSum(data) {
return data.reduce((sum, a) => sum + 1, 0);
}
const
data = [{ id: 'ddd6929eac', isComplete: true }, { id: 'a1dd9fbd0', isComplete: true }, { id: 'afa8ee064', isComplete: false }];
console.log(getSum(data));
Simply you can just add index:
const totalNum = data.reduce((sum, a, index) => index+1);
I have an array of objects. I want to loop trough that array and to check if an item match a criteria, using reduce method from javascript:
const arr = [{
value: 'test',
label: 'Test'
},
{
value: 'car',
label: 'Car'
},
]
const res = arr.reduce((acc, item) => {
if (item.value) {
acc.push({
element: item.label,
id: item.value,
})
}
if(item.value !== 'car') {
acc.push({element: 'here', id: 'here'})
}
return acc
}, [])
console.log(res)
Using if(item.value !== 'car') { acc.push({element: 'here', id: 'here'}) } i try to inspect if in my list is not at all a value that is not equal with 'car', then add that object, but it adds even if in the list exists car title, but what i want to achieve is to see if in the array is not any item that is equal with car, only after that to add that object. How to achieve that without using find() but only reduce()? Examples: 1. if i check the title car then that object should not be added . 2. If i check the title 'unknown', then that object should be added.
As I understood you only need to filter by some elements (not car elements). This way, you don't need to use "reducer", you can use "filter". Please, check the code below:
const arr = [{
value: 'test',
label: 'Test'
},
{
value: 'car',
label: 'Car'
},
];
// Using filter (recommended in your case)
// const notCarElements = arr.filter(elem => elem.value !== 'car');
// Using reducer
const notCarElements = arr.reduce((acc, item) => {
if (item.value === 'car') return acc;
acc.push(item);
return acc;
}, []);
console.log(notCarElements);
This question already has answers here:
How to change value of object which is inside an array using JavaScript or jQuery?
(34 answers)
Closed 2 years ago.
I have this array of objects:
const indexStates = [ {"4": true}, {"3": false}, {"7": false}, {"1": true} ];
and am trying to figure out how to change the value in a given object in this original array (do not want to make a copy of the array). I have tried this
index = 4;
indexStates.filter(o => o[index] = !o[index]);
console.log(indexStates);
but the result is
[{"4": false}, {"3": false, "4": true}, {"4": true, "7": false}, {"1": true, "4": true}]
instead of changing the value only in {"4": false} and leaving the other objects as is. What am I doing wrong? Also, I don't want to use third party libraries for this operation.
Few comments for your code:
index = 4;
indexStates.filter(o => o[index] = !o[index]);
this 'index' should be a property name, not a position in the array, and with o[index] = !o[index] its a assignment, not a predicate
Instead, Try this
var indexStates = [ {"4": true}, {"3": false}, {"7": false}, {"1": true} ];
var index = 4;
var toChange = indexStates.filter(o => Object.getOwnPropertyNames(o).filter(n => n == index)[0] !== undefined)[0];
toChange[index] = !toChange[index]
console.log(toChange);
console.log(indexStates);
What you are basically saying is:
filter this array to bring you only the items that the following action:
index "4" should be assigned with the opposite value
results into true, which means that the items that do not have index 4 (meaning its false in js) will be updated too.
What you need to do is:
console.log(indexStates.map(o => o[index] !== undefined ? {[index]: !o[index]} : o))
which will return a new array for you to use.
If you do not want to create a copy, you should go for for loop and check if the key/object exists int the current object and verify. If the value is there then negate it. Below is the snippet for the same. Hope this helps
const indexStates = [ {"4": true}, {"3": false}, {"7": false}, {"1": true} ];
index = "4";
const length = indexStates.length;
for(let i =0; i< length; i++) {
let elem = indexStates[i];
if(elem[index]) elem[index] = !elem[index]
}
console.log(indexStates);
If you can't make a copy of the array... then you could do this:
const getIndexOfTarget = (states, target) => {
const value = states.find(state => Object.keys(state)[0] === target)
return states.indexOf(value)
}
const states = [{"4": true}, {"3": false}, {"7": false}, {"1": true}];
const target = String(4)
const itemToChange = getIndexOfTarget(states, target)
states[itemToChange][target] = false // or !states[itemToChange][target]
Note I cast the index, or in this case target, to a String because that's what the key types are in the objects (you could just put "4" if you own it).
If you're going to have multiple "index" of the same value, then you'd need to swap the find with a filter.
const getIndexesOfTarget = (states, target) => {
const values = states.filter(state => Object.keys(state)[0] === target)
return values.map(val => states.indexOf(value))
}
const itemsToChange = getIndexesOfTarget(states, target)
itemsToChange.forEach(item => states[item][target] = !states[item][target])
I would go with a foreach approach
const indexStates = [ {"4": true}, {"3": false}, {"7": false}, {"1": true} ];
indexStates.forEach(elem => {
if(typeof elem[index] === 'undefined') return elem;
elem[index] = !elem[index];
return elem;
}
How about forEach. You can do it like this, if I understand your question correctly:
var indexStates = [ {"4": true}, {"3": false}, {"7": false}, {"1": true} ];
var target = '4';
indexStates.forEach(val=>{
if(Object.keys(val).includes(target)) val[target]=!val[target];
});
console.log(indexStates);
I have a database function that returns some rows from a sqlite database then stores that in state
rows = await ReturnSelectedSymbolsDB()
this.setState({ symbols: rows })
The array looks something like this
symbols: [{key: "0", symbol:"name1", active: false},{key:"1", symbol:"name2",active: false}]
I have another database function which returns some rows and I wish to add them to symbol so it would look like this.
symbols: [{key: "0", symbol:"name1", active: false, newKey: newValue},{key:"1", symbol:"name2",active: false, newKey, newValue2}]
The second function will return multiple rows from the database which will be easy to match up with symbols as symbols:symbol will match otherFunction:symbol.
Normally you would just write this like a regular SQL query with a inner join joining the 2 tables together and then just putting the resulting rows in a state variable but I cannot in this case and must build the state variable piece by piece.
Can this be done is regular javascript?
EDIT:
Probably wasnt clear but newKey can have different values depending on what the name of the symbol is
You can create a new util function where you can add new key to all object inside the array.
addKey(symbol) {
let newArray=[...symbol];
return newArray.map((ele, i) => {
return {...ele, newKey: newValue};
})
}
Happy Coding :)
You have to insert your new value into your first function array, there are couples of way can insert object in array either use for loop or array manipulation functions.
var arrOfObj = [{
key: "0",
symbol:"name1",
active: false
}, {
key: "1",
symbol:"name1",
active: false
}, {
key: "2",
symbol:"name1",
active: false
}];
var result = arrOfObj.map(function(o) {
o.newKey = newValue;
return o;
})
console.log(result)
Note: I would prefer to go with inner join with two tables to return
combine array that not require any array manipulation.
You could do something like this if you know the key value corresponding to a given symbol:
for (let i = 0; i < symbols.length; i++){
symbols[i].newKey = "anyValue"
}
Try this,
let symbols = [
{ key: "0", symbol: "name1", active: false },
{ key: "1", symbol: "name2", active: false }
];
let newSymbols = [
{ key: "1", symbol: "name1", newKey: "fdds" },
{ key: "0", symbol: "name2", newKey: "sadav" }
];
mergeArray = (arrayOld, arrayNew) => {
let output = arrayOld.filter(item => {
let find = findMatchingItem(arrayNew, item.key);
item["newKey"] = find.newKey;
return item;
});
return output;
};
findMatchingItem = (array, matchingItemKey) => {
let output = null;
array.map(item => {
if (item.key == matchingItemKey) {
output = item;
}
});
return output;
};
let newArray = mergeArray(symbols, newSymbols);
console.log(newArray);
I have matched objects using "key" if you want from "symbol" just change "key" to "symbol"