Issue in removing object using Lodash _remove - javascript

I am having an Object:
ids = [ "-LIof_e0hPtXKtkc4Uh9", "-LIjBcGO7m7VQ-B3pfYt" ]
If I Iterate using .map function of lodash
_.map(ids, (userID, key) => {
console.log('Lopping userId',userID);
})
it gives me value of each id.
Now when I am trying to remove it using _remove it is not working as expected.
_.remove(ids, (value, key, obj) => value == idToBeRemoved);
Still there is no difference in ids Object.
I am really new to angular4 and using lodash for the first time.
I just wanted to remove a value from ids object and get the remaining object.
Print of console.
I am using firebase and trying to delete data after retrieving it from firebase :
deleteTransactWith(transactWithKey,transactWithUser) {
let currentUser = this._authService.getLoggedInUser();
console.log(transactWithUser.groups)
console.log(Object.keys(transactWithUser.groups).length)
console.log('key To remove',transactWithKey)
for (var key in transactWithUser.groups) {
if (transactWithUser.groups.hasOwnProperty(key)) {
let group = this.firebase.object(`/url/${currentUser.$key}/${key}`);
group.snapshotChanges().take(1).subscribe((groupData: any) => {
groupData = groupData.payload.toJSON();
//console.log('not removed',groupData.userIds)
console.log('key',transactWithKey)
_.remove(groupData.userIds, (value) => value == transactWithKey);
//_.pull(groupData.userIds, transactWithKey);
console.log('removed',groupData.userIds)
});
}
}

You want _filter instead
const ids = [ "-LIof_e0hPtXKtkc4Uh9", "-LIjBcGO7m7VQ-B3pfYt" ]
const idToBeRemoved = "-LIof_e0hPtXKtkc4Uh9"
const filteredIds = _.filter(ids, function(id) { return id !== idToBeRemoved})
console.log(filteredIds)

You can simply use lodash _.pull
const _ = require("lodash");
const ids = [ "-LIof_e0hPtXKtkc4Uh9", "-LIjBcGO7m7VQ-B3pfYt" ]
const result = _.pull(ids, "-LIjBcGO7m7VQ-B3pfYt" )
console.log(filteredIds)

First find the index of what you are removed item and next pull out from it by _.pullAt(lodash)
let getIndex= _.findIndex(this.images, function(o) { return o.name == img.name; });
let removedImage = _.pullAt(this.images, getIndex) ;

Related

How can I add a string to a string value inside an object?

What im trying to do is to add a string id next to a value inside of an object.
So the object is like this:
["John","Mike"]
An item in the object is generated as soon the user clicks an add button
const handleAddClick = () => {
setLanguage([...language, ""]);
};
const handleItemChanged = (event, index) => {
const value = event.target.value;
const list = [...subtitle];
if (list.filter((f) => f === value).length > 0) {
setErrorValidation("Names cannot be equal!");
} else {
setErrorValidation("");
}
list[index] = value;
setName(list)
};
In the handleItemChanged, I tried to do this, but it didn't work.
let string = "test"
list[index] = value + string;
setName(list)
So what I want is to add a string to a new value that is added to the list
["Johntest", "Miketest"]
How can I solve this?
You can use map before assigning value:
// ... the other code is omitted for the brevity
list.map(item => item + "test")
setName(list)
An example:
let arr = ["John", "Mike"]
arr = arr.map(item => item + " test")
console.log(arr)
Calling setName(list) does not trigger a rerender for the simple reason that list is still the same object. setState will only work if the previous and new value is different. For objects, they are shallowly compared.
That is why it is suggested to create a new array using .map():
let string = "test"
const newList = list.map(e => e+urString)
setName(newList)

Destruct a string from split to named object

I am investigating how create a named object in one go, using destruct
A search for javascript destruct* split object did not reveal how to directly destruct a string into an object using split.
I do not mean reduce or map but pure destructing
const list = { ..... } = `......`.split(..)
or at least
const rowItem = { ..... } = `......`.split(..)
My initial version works, but there should be a neater way with less steps
The initial split on lines is fine. It is the filling of the list using destruct I am curious about
const rows = `100|Description 1|a|
101|Description 2|a|
102|Description 3|b|`.split("\n")
let list = {}
rows.forEach(row => {
const [ProductId, Description, subCat, ] = row.split("|")
list[ProductId] = {"Description": Description, "subCat": subCat }
})
console.log(list)
You can do something like this with IIFE
const rows = `100|Description 1|a|
101|Description 2|a|
102|Description 3|b|`.split("\n")
let list = {}
rows.forEach(row => {
(([ProductId, Description, subCat]) => (list[ProductId] = {
Description,
subCat
}))(row.split("|"))
})
console.log(list)
You can consider using Object.fromEntries if it's available in your environment
const rows = Object.fromEntries(`100|Description 1|a|
101|Description 2|a|
102|Description 3|b|`
.split("\n")
.map(row => row.split('|'))
.map(([key, Description, subCat]) => [key, { Description, subCat }])
);
console.log(rows);
It is possible to set the property to an existing object while destructuring.
const row = { Description: 'Description 1', subCat: 'a' },
o = { }; // existing object to be updated;
({ Description: o.Description, subCat: o.subCat } = row);
console.log(o)
In your case, you have dynamic id keys, nested property updates and you are destructuring an array instead of an object. It becomes complex, but it is possible to apply the above logic to your code (This is extremely hackish and purely academic. This should never ever be used in an actual code base)
const str = "100|Description 1|a|",
splits = str.split('|'),
list = {};// existing object
({ 0: id, [-1]: list[id]= {}, 1: list[id].Description, 2: list[id].subCat } = splits)
console.log(list)
This destructures the array like an object. It gets the property with key 0 and sets it to the id variable. Then destructure the -1 property. This is non-existent, so the default value is used and list[id] = {} is set.
This is how the transpiled code looks like:
var _str$split = str.split('|');
id = _str$split[0];
list[id] = _str$split[-1] === undefined ? {} : _str$split[-1];
list[id].Description = _str$split[1];
list[id].subCat = _str$split[2];
console.log(list);
Applying this to your original snippet:
const rows = `100|Description 1|a|
101|Description 2|a|
102|Description 3|b|`
let list = {},
id;
rows.split("\n")
.forEach(str => ({
0: id,
[-1]: list[id] = {},
1: list[id].Description,
2: list[id].subCat
} = str.split('|'))
)
console.log(list)
Another option is to use matchAll and Object.fromEntries()
const str = `100|Description 1|a|
101|Description 2|a|
102|Description 3|b|`;
const regex = /(\d+)\|([^|]+)\|(\w+)/g;
const output = Object.fromEntries(
Array.from(
str.matchAll(regex), ([, id, Description, subCat]) => [id, { Description, subCat }]
)
)
console.log(output)
matchAll is still in Draft stage but it is implemented except by IE and Safari. You can easily polyfill it. It is basically looping through exec results

Find an index of array item from another json array item

I am looking to find out an index and group the item belong to in a parent json group, how can I do it?
I am open to reformat the json as well if need be,
I tried JSON.stringify() but it returns the wrong index as well.
let Content = {
group1: [
[{content:"hello"},{content:"world"}],
[{content:"hello1"},{content:"world"}],
[{content:"hello2"},{content:"world"}],
[{content:"hello3"},{content:"world"}],
[{content:"hello4"},{content:"world"}],
[{content:"hello5"},{content:"world"}],
],
group2: [
[{content:"hello10"},{content:"world"}],
[{content:"hello11"},{content:"world"}],
[{content:"hello12"},{content:"world"}],
[{content:"hello13"},{content:"world"}],
[{content:"hello14"},{content:"world"}],
[{content:"hello15"},{content:"world"}],
],
};
// let currentItem = {type:'group2',index:5};
// let currentItemContent = Content[currentItem.type][currentItem.index];
let obj = [{content:"hello15"},{content:"world"}];
let newIndex = Content["group1"].indexOf(obj);
let type = "group1";
if(newIndex < 0)
{
type="group2"
console.log(Content["group2"]);
newIndex = Content["group2"].indexOf(obj);
}
console.log({"type":type,"index":newIndex});
expected: {type:'group2',index:5}
Loop through the Content object using for...in. Check if the given array is in each group by using findIndex. Since both the objects in the array seem to be in order, you can simply compare the string returned by JSON.stringify
let Content={group1:[[{content:"hello"},{content:"world"}],[{content:"hello1"},{content:"world"}],[{content:"hello2"},{content:"world"}],[{content:"hello3"},{content:"world"}],[{content:"hello4"},{content:"world"}],[{content:"hello5"},{content:"world"}]],group2:[[{content:"hello10"},{content:"world"}],[{content:"hello11"},{content:"world"}],[{content:"hello12"},{content:"world"}],[{content:"hello13"},{content:"world"}],[{content:"hello14"},{content:"world"}],[{content:"hello15"},{content:"world"}]]}
function find(input, search) {
for (const type in input) {
const group = input[type];
const index = group.findIndex(a => JSON.stringify(a) === JSON.stringify(search));
if (index != -1)
return { type, index }
}
return null
}
console.log(find(Content, [{content:"hello15"},{content:"world"}]))
console.log(find(Content, [{content:"hello"},{content:"world"}]))
You could also use Array.find in combination with Object.keys and Array.some. The array comparison you can do via JSON.stringify however remember that if your keys are in different order that would not work:
[{content:"world"},{content:"hello"}] vs [{content:"hello"},{content:"world"}]
would not match as you would expect since you are matching on strings and they are now different.
let Content = { group1: [ [{content:"hello"},{content:"world"}], [{content:"hello1"},{content:"world"}], [{content:"hello2"},{content:"world"}], [{content:"hello3"},{content:"world"}], [{content:"hello4"},{content:"world"}], [{content:"hello5"},{content:"world"}], ], group2: [ [{content:"hello10"},{content:"world"}], [{content:"hello11"},{content:"world"}], [{content:"hello12"},{content:"world"}], [{content:"hello13"},{content:"world"}], [{content:"hello14"},{content:"world"}], [{content:"hello15"},{content:"world"}], ], };
let findArray = (data, obj) => {
let index, group = Object.keys(data).find((k,i) => {
index = i
return data[k].some(x => JSON.stringify(x) === JSON.stringify(obj))
})
return { index, group }
}
console.log(findArray(Content, [{content:"hello"},{content:"world"}]))
console.log(findArray(Content, [{content:"hello10"},{content:"world"}]))

How to return specific properties of objects in form of array in javascript

I have a function that takes an array of dog objects and returns an array of the specific properties
The code that I have tried
function Owner(dogs) {
dogs.map(value => {
if (value.breed === 'GermanShepherd') {
return value.owner;
}
}
One option is using reduce() and check if the breed if same with search variable, if it is, use concat() to add to the accumulator.
let arr = [{"name":"Beatrice","breed":"Lurcher","owner":"Tom"},{"name":"Max","breed":"GermanShepherd","owner":"Malcolm"},{"name":"Poppy","breed":"GermanShepherd","owner":"Vikram"}];
let search = 'GermanShepherd';
let result = arr.reduce((c, v) => v.breed === search ? c.concat(v.owner) : c, []);
console.log(result);
You can also use filter and map combo.
let arr = [{"name":"Beatrice","breed":"Lurcher","owner":"Tom"},{"name":"Max","breed":"GermanShepherd","owner":"Malcolm"},{"name":"Poppy","breed":"GermanShepherd","owner":"Vikram"}]
let search = 'GermanShepherd';
let result = arr.filter(o => o.breed === search).map(o => o.owner);
console.log(result);

Java script filter on array of objects and push result's one element to another array

I have a array called data inside that array I have objects.
An object structure is like this
{
id:1,
especial_id:34,
restaurant_item:{id:1,restaurant:{res_name:'KFC'}}
}
I want to pass a res_name eg:- KFC
I want an output as a array which consists all the especial_ids
like this
myarr = [12,23,23]
I could do something like this for that. But I want to know what is more elegant way to do this.
const data = [
{id:1,especial_id:6,restaurant_items:{id:5,res_name:'McDonalds'}},
{id:1,especial_id:8,restaurant_items:{id:5,res_name:'Kfc'}},
{id:1,especial_id:6,restaurant_items:{id:5,res_name:'Sunmeal'}},
{id:1,especial_id:6,restaurant_items:{id:5,res_name:'Kfc'}},
];
let temp = data.filter(element => element.restaurant_items.res_name == 'kfc')
let myArr = [];
temp.forEach(element=> myArr.push(element.especial_id));
console.log(myArr)//[8,6]
You can try this. It uses "Array.filter" and "Array.map"
var data = [
{id:1,especial_id:6,restaurant_items:{id:5,res_name:'McDonalds'}},
{id:1,especial_id:8,restaurant_items:{id:5,res_name:'Kfc'}},
{id:1,especial_id:6,restaurant_items:{id:5,res_name:'Sunmeal'}},
{id:1,especial_id:6,restaurant_items:{id:5,res_name:'Kfc'}},
];
function getEspecialIdsByName(name) {
return data.filter(d => d.restaurant_items.res_name.toLowerCase() == name.toLowerCase())
.map(d => d.especial_id)
}
console.log(getEspecialIdsByName('Kfc'))
console.log(getEspecialIdsByName('Sunmeal'))
You can reduce to push elements which pass the test to the accumulator array in a single iteration over the input:
const data = [
{id:1,especial_id:6,restaurant_items:{id:5,res_name:'McDonalds'}},
{id:1,especial_id:8,restaurant_items:{id:5,res_name:'Kfc'}},
{id:1,especial_id:6,restaurant_items:{id:5,res_name:'Sunmeal'}},
{id:1,especial_id:6,restaurant_items:{id:5,res_name:'Kfc'}},
];
console.log(
data.reduce((a, { especial_id, restaurant_items: { res_name }}) => {
if (res_name === 'Kfc') a.push(especial_id)
return a;
}, [])
);
Use Array.reduce
const data = [{id:1,especial_id:6,restaurant_items:{id:5,res_name:'McDonalds'}},{id:1,especial_id:8,restaurant_items:{id:5,res_name:'Kfc'}},{id:1,especial_id:6,restaurant_items:{id:5,res_name:'Sunmeal'}},{id:1,especial_id:6,restaurant_items:{id:5,res_name:'Kfc'}}];
let result = data.reduce((a,c) => {
if(c.restaurant_items.res_name === 'Kfc') a.push(c.especial_id);
return a;
},[]);
console.log(result);

Categories

Resources