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);
Related
I want to filter items from the list. When a certain category will be provided as a value to the target variable, the filter method should return only items with that category. but when no category is provided I want to get items of all categories regardless of category. In my code below works ok, but I want more clear logic to filter items when no category is provided as a target.
let items = [
{'name':"A",'category':"a"},
{'name':"B",'category':"b"},
{'name':"C",'category':"c"}
]
let target;
console.log(items.filter( item => {
if(target==undefined){
return true;
}
return (item['category']===target);
}));
You can create a function that takes a list of items and an optional target. In case a target was passed return the filtered list, otherwise, return the list itself:
const filterByCategoryIfTargetProvided = (arr = [], target) =>
target ? arr.filter(({ category }) => category === target) : arr;
const items = [ {'name':"A",'category':"a"}, {'name':"B",'category':"b"}, {'name':"C",'category':"c"} ];
console.log( filterByCategoryIfTargetProvided(items) );
console.log( filterByCategoryIfTargetProvided(items, 'a') );
You coiuld filter by either no category or with the category.
const
filter = (data, category) => data.filter(o => !category || o.category === category),
items = [{ name: "A", category: "a" }, { name: "B", category: "b" }, { name: "C", category: "c" }];
console.log(filter(items));
console.log(filter(items, 'a'));
.as-console-wrapper { max-height: 100% !important; top: 0; }
This function requires an array and the object you want to filter. You can use it to filter the object based on the category, name or any other object key. Thanks.
let items = [
{ name: "A", category: "a" },
{ name: "B", category: "b" },
{ name: "C", category: "c" },
];
const filterItems = (arr, itemToFilter) => {
if (itemToFilter) {
const keyToFilter = Object.keys(itemToFilter);
const filteredItem = arr.filter((eachItem) => {
return eachItem[keyToFilter] === itemToFilter[keyToFilter];
});
return filteredItem;
} else {
return arr;
}
};
console.log(filterItems(items, { category: "a" }));
I tried to print "person[0].name: a" and "person[1].name: b" and so on, based on this person array of object:
I used object entries twice, any other way I can make the loop more efficient?
const person = [{
name: 'a',
}, {
name: 'b'
}]
Object.entries(person).forEach(([key, value]) => {
Object.entries(value).forEach(([key2, value2]) => {
console.log(`person[${key}].${key2}`, ':', value2)
})
})
You could take a recursive approach and hand over the parent path.
const
show = (object, parent) => {
const wrap = Array.isArray(object) ? v => `[${v}]` : v => `.${v}`;
Object.entries(object).forEach(([k, v]) => {
if (v && typeof v === 'object') show(v, parent + wrap(k));
else console.log(parent + wrap(k), v);
});
},
person = [{ name: 'a' }, { name: 'b' }];
show(person, 'person');
You don't really need the first call. person is already an Array.
const person = [{
name: 'a',
}, {
name: 'b'
}]
person.forEach((value, key) => {
Object.entries(value).forEach(([key2, value2]) => {
console.log(`person[${key}].${key2}`, ':', value2)
})
})
Just in case forEach is for side effects. If you want to create another array with transformed values you better use map/flatMap instead.
const person = [{
name: 'a',
}, {
name: 'b'
}]
const transformed = person.flatMap((value, key) => {
return Object.entries(value).map(([key2, value2]) => `person[${key}].${key2}:${value2}`)
})
console.log(transformed)
You can also try something like this, with only one forEach() loop
const person = [{
name: 'a',
},{
name: 'b'
}];
person.forEach((el,i) => {
let prop = Object.keys(el).toString();
console.log(`person[${i}].${prop}`, ':', el[prop])
});
Im adding a checkbox options and only have to update my object with a new key
so if I uncheck a item in a list i want to update the object
[ { id: 1 }, { id: 2 } ]
after unchecked:
[ { id: 1 }, { id: 2, unChecked: false } ]
any method to toggle this states?
thanks in advance
You can do it using native javascript and array map method. In the function check if the id matches then add the key there
let obj = [{
id: 1
}, {
id: 2
}]
function updateObj(obj, objId, key) {
return obj.map((item) => {
if (item.id === objId) {
return {
id: item.id,
[key]: false
}
} else {
return {
id: item.id
}
}
})
}
console.log(updateObj(obj, 2, 'unchecked'))
You can do this without lodash and using the .map method by adding the unChecked property if the id is not in the checked array by using .includes().
See working example below:
const checked = [2, 3], /* array holding all checked values */
arr = [{id: 1}, {id: 2}],
res = arr.map(({id}) => checked.includes(id) ? {id, unChecked: false} : {id});
console.log(res);
My array looks like this:
array = [object {id: 1, value: "itemname"}, object {id: 2, value: "itemname"}, ...]
all my objects have the same attibutes, but with different values.
Is there an easy way I can use a WHERE statement for that array?
Take the object where object.id = var
or do I just need to loop over the entire array and check every item? My array has over a 100 entries, so I wanted to know if there was a more efficient way
Use Array.find:
let array = [
{ id: 1, value: "itemname" },
{ id: 2, value: "itemname" }
];
let item1 = array.find(i => i.id === 1);
Array.find at MDN: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/find
I'd use filter or reduce:
let array = [
{ id: 1, value: "itemname" },
{ id: 2, value: "itemname" }
];
let item1 = array.filter(item => item.id === 1)[0];
let item2 = array.reduce((prev, current) => prev || current.id === 1 ? current : null);
console.log(item1); // Object {id: 1, value: "itemname"}
console.log(item2); // Object {id: 1, value: "itemname"}
(code in playground)
If you care about iterating over the entire array then use some:
let item;
array.some(i => {
if (i.id === 1) {
item = i;
return true;
}
return false;
});
(code in playground)
You can search a certain value in array of objects using TypeScript dynamically if you need to search the value from all fields of the object without specifying column
var searchText = 'first';
let items = [
{ id: 1, name: "first", grade: "A" },
{ id: 2, name: "second", grade: "B" }
];
This below code will search for the value
var result = items.filter(item =>
Object.keys(item).some(k => item[k] != null &&
item[k].toString().toLowerCase()
.includes(searchText.toLowerCase()))
);
Same approach can be used to make a Search Filter Pipe in angularjs 4 using TypeScript
I had to declare the type to get it to work in typescript:
let someId = 1
array.find((i: { id: string; }) => i.id === someId)
You'll have to loop over the array, but if you make a hashmap to link each id to an index and save that, you only have to do it once, so you can reference any objeft after that directly:
var idReference = myArray.reduce(function( map, record, index ) {
map[ record.id ] = index;
return map;
}, {});
var objectWithId5 = myArray[ idReference["5"] ];
This does assume all ids are unique though.
I have an array of objects and I want to get a new array from it that is unique based only on a single property, is there a simple way to achieve this?
Eg.
[ { id: 1, name: 'bob' }, { id: 1, name: 'bill' }, { id: 1, name: 'bill' } ]
Would result in 2 objects with name = bill removed once.
Use the uniq function
var destArray = _.uniq(sourceArray, function(x){
return x.name;
});
or single-line version
var destArray = _.uniq(sourceArray, x => x.name);
From the docs:
Produces a duplicate-free version of the array, using === to test object equality. If you know in advance that the array is sorted, passing true for isSorted will run a much faster algorithm. If you want to compute unique items based on a transformation, pass an iterator function.
In the above example, the function uses the objects name in order to determine uniqueness.
If you prefer to do things yourself without Lodash, and without getting verbose, try this uniq filter with optional uniq by property:
const uniqFilterAccordingToProp = function (prop) {
if (prop)
return (ele, i, arr) => arr.map(ele => ele[prop]).indexOf(ele[prop]) === i
else
return (ele, i, arr) => arr.indexOf(ele) === i
}
Then, use it like this:
const obj = [ { id: 1, name: 'bob' }, { id: 1, name: 'bill' }, { id: 1, name: 'bill' } ]
obj.filter(uniqFilterAccordingToProp('abc'))
Or for plain arrays, just omit the parameter, while remembering to invoke:
[1,1,2].filter(uniqFilterAccordingToProp())
If you want to check all the properties then
lodash 4 comes with _.uniqWith(sourceArray, _.isEqual)
A better and quick approach
var table = [
{
a:1,
b:2
},
{
a:2,
b:3
},
{
a:1,
b:4
}
];
let result = [...new Set(table.map(item => item.a))];
document.write(JSON.stringify(result));
Found here
You can use the _.uniqBy function
var array = [ { id: 1, name: 'bob' }, { id: 2, name: 'bill' }, { id: 1, name: 'bill' },{ id: 2, name: 'bill' } ];
var filteredArray = _.uniqBy(array,function(x){ return x.id && x.name;});
console.log(filteredArray)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>
In the above example, filtering is based on the uniqueness of combination of properties id & name.
if you have multiple properties for an object.
then to find unique array of objects based on specific properties, you could follow this method of combining properties inside _.uniqBy() method.
I was looking for a solution which didn't require a library, and put this together, so I thought I'd add it here. It may not be ideal, or working in all situations, but it's doing what I require, so could potentially help someone else:
const uniqueBy = (items, reducer, dupeCheck = [], currentResults = []) => {
if (!items || items.length === 0) return currentResults;
const thisValue = reducer(items[0]);
const resultsToPass = dupeCheck.indexOf(thisValue) === -1 ?
[...currentResults, items[0]] : currentResults;
return uniqueBy(
items.slice(1),
reducer,
[...dupeCheck, thisValue],
resultsToPass,
);
}
const testData = [
{text: 'hello', image: 'yes'},
{text: 'he'},
{text: 'hello'},
{text: 'hell'},
{text: 'hello'},
{text: 'hellop'},
];
const results = uniqueBy(
testData,
item => {
return item.text
},
)
console.dir(results)
In case you need pure JavaScript solution:
var uniqueProperties = {};
var notUniqueArray = [ { id: 1, name: 'bob' }, { id: 1, name: 'bill' }, { id: 1, name: 'bill' } ];
for(var object in notUniqueArray){
uniqueProperties[notUniqueArray[object]['name']] = notUniqueArray[object]['id'];
}
var uniqiueArray = [];
for(var uniqueName in uniqueProperties){
uniqiueArray.push(
{id:uniqueProperties[uniqueName],name:uniqueName});
}
//uniqiueArray
unique array by id property with ES6:
arr.filter((a, i) => arr.findIndex(b => b.id === a.id) === i); // unique by id
replace b.id === a.id with the relevant comparison for your case