Remove entire key when matched with matched array values - javascript

I am new to react, I have an object and an array, I want to get details of unmatched items from the object when compared with array values. I tried but shows all the data when consol.log. here is my code
var content:[
0:{id:20, name:'Jack Daniel'}
1:{id:21, name:'Sophie McDonald'}
2:{id:22, name:'Jason Thomas'}
3:{id:23, name:'Chris Williams'}
]
var filter:[Sophie McDonald, Chris Williams]
filterValues = content.filter(item=> {
for(var i = 0;i<filter.length;i++) {
if (item.name === filtered[i])
{
return item
}
}
});
console.log(filteredValues)
// returns 0:{id:21, name:'Sophie McDonald'}
// 1:{id:23, name:'Chris Williams'}
But I need unmatched results,
filterValues = content.filter(item=> {
for(var i = 0;i<filter.length;i++) {
if (item.name !== filtered[i])
{
return item
}
}
});
console.log(filteredValues)
// returns 0:{id:20, name:'Jack Daniel'}
// 1:{id:21, name:'Sophie McDonald'}
// 2:{id:22, name:'Jason Thomas'}
// 3:{id:23, name:'Chris Williams'}
Result must be
0:{id:20, name:'Jack Daniel'}
1:{id:22, name:'Jason Thomas'}

Try using filter, checking if the values of the array are present in your object values:
const content = [{
id: 20,
name: 'Jack Daniel'
},
{
id: 21,
name: 'Sophie McDonald'
},
{
id: 22,
name: 'Jason Thomas'
},
{
id: 23,
name: 'Chris Williams'
}
];
const values = ['Sophie McDonald', 'Chris Williams'];
const filteredValues = content.filter(({
name
}) => !values.includes(name));
console.log(filteredValues);

Seems to work with a few edits to the format:
let content = [
{id:20, name:'Jack Daniel'},
{id:21, name:'Sophie McDonald'},
{id:22, name:'Jason Thomas'},
{id:23, name:'Chris Williams'}
]
let filter = ["Sophie McDonald", "Chris Williams"]
let filterValues = content.filter(item=> {
for(var i = 0;i<filter.length;i++) {
if (item.name !== filter[i]){
return item
}
}
});
console.log(filterValues)

Related

Create unique values from duplicates in Javascript array of objects

I have an array of duplicated objects in Javascript. I want to create an array of unique objects by adding the index of occurrence of the individual value.
This is my initial data:
const array= [
{name:"A"},
{name:"A"},
{name:"A"},
{name:"B"},
{name:"B"},
{name:"C"},
{name:"C"},
];
This is expected end result:
const array= [
{name:"A-0"},
{name:"A-1"},
{name:"A-2"},
{name:"B-0"},
{name:"B-1"},
{name:"C-0"},
{name:"C-1"},
];
I feel like this should be fairly simple, but got stuck on it for a while. Can you please advise how I'd go about this? Also if possible, I need it efficient as the array can hold up to 1000 items.
EDIT: This is my solution, but I don't feel like it's very efficient.
const array = [
{ name: "A" },
{ name: "A" },
{ name: "C" },
{ name: "B" },
{ name: "A" },
{ name: "C" },
{ name: "B" },
];
const sortedArray = _.sortBy(array, 'name');
let previousItem = {
name: '',
counter: 0
};
const indexedArray = sortedArray.map((item) => {
if (item.name === previousItem.name) {
previousItem.counter += 1;
const name = `${item.name}-${previousItem.counter}`;
return { name };
} else {
previousItem = { name: item.name, counter: 0};
return item;
}
});
Currently you are sorting it first then looping over it, which may be not the most efficient solution.
I would suggest you to map over it with a helping object.
const a = [{name:"A"},{name:"A"},{name:"A"},{name:"B"},{name:"B"},{name:"C"},{name:"C"},], o = {};
const r = a.map(({ name }) => {
typeof o[name] === 'number' ? o[name]++ : o[name] = 0;
return { name: `${name}-${o[name]}` };
});
console.log(r);
Keep a counter, and if the current name changes, reset the counter.
This version mutates the objects. Not sure if you want a copy or not. You could potentially sort the array by object name first to ensure they are in order (if that's not already an existing precondition.)
const array = [
{ name: "A" },
{ name: "A" },
{ name: "A" },
{ name: "B" },
{ name: "B" },
{ name: "C" },
{ name: "C" },
];
let name, index;
for (let i in array) {
index = array[i].name == name ? index + 1 : 0;
name = array[i].name;
array[i].name += `-${index}`;
}
console.log(array);
Another way, if you don't want to sort, and don't want to mutate any objects, is to use a map and keep track of the current index for each object.
const array = [
// NOTE: I put the items in mixed up order.
{ name: "A" },
{ name: "C" },
{ name: "A" },
{ name: "B" },
{ name: "A" },
{ name: "C" },
{ name: "B" },
];
let index = {};
let next = name => index[name] = index[name] + 1 || 0;
let result = array.map(obj => ({ ...obj, name: obj.name + '-' + next(obj.name) }));
console.log(result);

.splice() is removing 2 objects from array instead of 1

When typing in 'John Smith' for example, slice removes the first two employee names instead of only John's. Any idea why this is happening?
let removeEmployee = '';
let employees = [
{
name: 'John Smith'
}, {
name: 'Jackie Jackson'
}, {
name: 'Chris Jones'
}, {
name: 'Amanda Cullen'
}, {
name: 'Jeremy Goodwin'
}, ]
removeEmployee = prompt('Enter the name of the employee to be removed:');
function employeeExists(employee) {
return employees.some(function(el) {
return el.name === employee;
});
}
if (employeeExists(removeEmployee)) {
employees.forEach(function(employee, index, object) {
if (employee.name === removeEmployee) {
object.splice(index, 1);
} else {
console.log(employee.name);
}
});
} else {
console.log('That employee does not exist, please try again.');
}
You could make things a little simpler using filter instead of forEach:
if (employeeExists(removeEmployee)) {
employees = employees.filter(e => e.name !== removeEmployee);
}
If you still want to use splice, you could use findIndex with it:
let employees = [ {name: 'John Smith'}, {name: 'Jackie Jackson'}, {name: 'Chris Jones'}, {name: 'Amanda Cullen'}, {name: 'Jeremy Goodwin'} ];
var removeEmployee = 'Chris Jones';
var index = employees.findIndex(e => e.name === removeEmployee);
employees.splice(index, 1);
console.log(employees);
Jackie Jackson still in the list
You loop through the list like this:
1
2
3
4
5
for the first iterration you are at index 0. Then you remove index 0 (John Smith). At this point Jackie Jackson is the new index 0 but the iterration jumps to the next element (index 1), what is Chris Jones.
The new index 0 is never logged out to the console! But he is still in the list!
You can use findIndex to find the index of the object where name is same as the input of the prompt. Using that index you can use splice to remove item from employees array
let removeEmployee = '';
let employees = [{
name: 'John Smith'
}, {
name: 'Jackie Jackson'
}, {
name: 'Chris Jones'
}, {
name: 'Amanda Cullen'
}, {
name: 'Jeremy Goodwin'
}, ]
removeEmployee = prompt('Enter the name of the employee to be removed:');
function employeeExists(employee) {
let ifEmployee = employees.findIndex(function(el) {
return el.name === employee.trim();
})
return ifEmployee;
}
var employeIndex = employeeExists(removeEmployee);
if (employeIndex !== -1) {
employees.splice(employeIndex, 1)
} else {
console.log('That employee does not exist, please try again.');
}
console.log(employees)
You do not need third third parameter in forEach. Just simply splice the employees array as below.
let removeEmployee = '';
let employees = [{
name: 'John Smith'
}, {
name: 'Jackie Jackson'
}, {
name: 'Chris Jones'
}, {
name: 'Amanda Cullen'
}, {
name: 'Jeremy Goodwin'
}, ]
// let letters = ['a', 'd', 'c']
removeEmployee = prompt('Enter the name of the employee to be removed:');
function employeeExists(employee) {
return employees.some(function(el) {
return el.name === employee;
});
}
if (employeeExists(removeEmployee)) {
employees.forEach(function(employee, index) {
if (employee.name === removeEmployee) {
employees.splice(index, 1);
} else {
console.log(employee.name);
}
});
} else {
console.log('That employee does not exist, please try again.');
}
console.log(employees)
Simply use the Array#filter function to remove the items. You don't need first to check (iteration) and then loop with forEach(iteration). You have 2 iterations. You can do it only during one iteration.
let employees = [
{ name: 'John Smith', },
{ name: 'Jackie Jackson' },
{ name: 'Chris Jones' },
{ name: 'Amanda Cullen' },
{ name: 'Jeremy Goodwin'}
];
let name = prompt('Enter the name of the employee to be removed:');
employees = employees.filter(emp => emp.name.localeCompare(name));
console.log(employees);

Mapping an org chart into a hash table

Hey all I'm trying to take an array of objects(employees) and map them to a new object in order to depict the hierarchy of the org. So each manager would have a key and an array attached to the key holding all the names of their reports.
I'm unsure why I am unable to push my employee names to their respective manager's array. This seems to set my object keys to arrays rather than 1,2,3,4.
Anyone pointers would be appreciated.
Repl.it: https://repl.it/JeMh/2
let data = [
{
name: 'ceo',
id: 1,
mgr: null,
},
{
name: 'vp1',
id: 2,
mgr: 1,
},
{
name: 'vp2',
id:3,
mgr: 1,
},
{
name: 'mgr',
id:4,
mgr: 2,
},
];
function displayOrg(data) {
let org = {};
for(let i = 0; i < data.length; i++) {
let current = data[i];
for(let key in current){
if(org[key] !== current.id || current.mgr){
org[current.id] = []
}
}
for(let key in org){
console.log(current.mgr);
console.log(org[key])
if(current.mgr === org[key]){
console.log("THIS HAPPEN");
org[key].push(current.name);
}
}
}
return org;
}
displayOrg(data);
expected resulted: { '1': [vp1,vp2], '2': [mgr], '3': [], '4': [] }
looks pretty straight forward:
function getMngd(data, mngrId){
return data.filter(emp => emp.mgr === mngrId).map(emp => emp.name)
}
data.reduce((p,c)=>{
const {id} = c;
p[id] = getMngd(data, id);
return p;
},{})

Create new array from iterating JSON objects and getting only 1 of its inner array

See jsfiddle here: https://jsfiddle.net/remenyLx/2/
I have data that contains objects that each have an array of images. I want only the first image of each object.
var data1 = [
{
id: 1,
images: [
{ name: '1a' },
{ name: '1b' }
]
},
{
id: 2,
images: [
{ name: '2a' },
{ name: '2b' }
]
},
{
id: 3
},
{
id: 4,
images: []
}
];
var filtered = [];
var b = data1.forEach((element, index, array) => {
if(element.images && element.images.length)
filtered.push(element.images[0].name);
});
console.log(filtered);
The output needs to be flat:
['1a', '2a']
How can I make this prettier?
I'm not too familiar with JS map, reduce and filter and I think those would make my code more sensible; the forEach feels unnecessary.
First you can filter out elements without proper images property and then map it to new array:
const filtered = data1
.filter(e => e.images && e.images.length)
.map(e => e.images[0].name)
To do this in one loop you can use reduce function:
const filtered = data1.reduce((r, e) => {
if (e.images && e.images.length) {
r.push(e.images[0].name)
}
return r
}, [])
You can use reduce() to return this result.
var data1 = [{
id: 1,
images: [{
name: '1a'
}, {
name: '1b'
}]
}, {
id: 2,
images: [{
name: '2a'
}, {
name: '2b'
}]
}, {
id: 3
}, {
id: 4,
images: []
}];
var result = data1.reduce(function(r, e) {
if (e.hasOwnProperty('images') && e.images.length) r.push(e.images[0].name);
return r;
}, [])
console.log(result);
All answers are creating NEW arrays before projecting the final result : (filter and map creates a new array each) so basically it's creating twice.
Another approach is only to yield expected values :
Using iterator functions
function* foo(g)
{
for (let i = 0; i < g.length; i++)
{
if (g[i]['images'] && g[i]["images"].length)
yield g[i]['images'][0]["name"];
}
}
var iterator = foo(data1) ;
var result = iterator.next();
while (!result.done)
{
console.log(result.value)
result = iterator.next();
}
This will not create any additional array and only return the expected values !
However if you must return an array , rather than to do something with the actual values , then use other solutions suggested here.
https://jsfiddle.net/remenyLx/7/

Find object in array and change its property if I know its other property

I've got an array of objects and I need a function that finds object an array by the objects property (id in example) and changes its other property (name in example). Currently my implementation looks like this:
var arrayOfObjects = [{
id: 1,
name: 'Alpha'
}, {
id: 2,
name: 'Bravo'
}];
var setNameById = function (id, newName) {
arrayOfObjects.filter(function(obj) {return obj.id === id;}).name = newName;
};
console.log(JSON.stringify(arrayOfObjects)); // initial array logged
setNameById(2, 'Charlie');
console.log(JSON.stringify(arrayOfObjects)); // initial array logged
I understand that the problem is in changing the object that is returned by filter and not initial one, but I haven't found implementations that give access to initial object in such a situation, is it possible or do I need to rethink the steps that led me to this point.
Use this instead of filter. Filter produce new array.
arrayOfObjects.forEach(function(v){
if (v.id == id) {v.name = newName}
});
Use Array#forEach over Array#filter
Note that == or === should be used to compare, = will assign the value!
Array#forEach with condition should be enough just to update existing array of object.
var arrayOfObjects = [{
id: 1,
name: 'Alpha'
}, {
id: 2,
name: 'Bravo'
}];
var setNameById = function(id, newName) {
var filtered = arrayOfObjects.filter(function(obj) {
return obj.id == id;
});
filtered.forEach(function(el) {
el.name = newName;
});
return filtered;
};
console.log(JSON.stringify(arrayOfObjects));
var filtered = setNameById(2, 'Charlie');
console.log(JSON.stringify(filtered));
Or use Array#map
var arrayOfObjects = [{
id: 1,
name: 'Alpha'
}, {
id: 2,
name: 'Bravo'
}];
var setNameById = function(id, newName) {
return arrayOfObjects.filter(function(obj) {
return obj.id == id;
}).map(function(el) {
el.name = newName;
return el;
});
};
console.log(JSON.stringify(arrayOfObjects));
var filtered = setNameById(2, 'Charlie');
console.log(JSON.stringify(filtered));
Filter returns an array. So will have to use index in your approach.
Your Approach
var arrayOfObjects = [{
id: 1,
name: 'Alpha'
}, {
id: 2,
name: 'Bravo'
}];
var setNameById = function(id, newName) {
arrayOfObjects.filter(function(obj) {
return obj.id = id;
})[0].name = newName;
};
console.log(JSON.stringify(arrayOfObjects)); // initial array logged
setNameById(2, 'Charlie');
console.log(JSON.stringify(arrayOfObjects));
array.find
If you are sure it will return only one value, use array.find
var arrayOfObjects = [{
id: 1,
name: 'Alpha'
}, {
id: 2,
name: 'Bravo'
}];
var setNameById = function(id, newName) {
arrayOfObjects.find(function(obj) {
return obj.id = id;
}).name = newName;
};
console.log(JSON.stringify(arrayOfObjects)); // initial array logged
setNameById(2, 'Charlie');
console.log(JSON.stringify(arrayOfObjects));
array.forEach
If there can be more than 1 object with same search key (id in this case), use array.forEach instead of array.filter and then loop over filtered array
var arrayOfObjects = [{
id: 1,
name: 'Alpha'
}, {
id: 2,
name: 'Bravo'
}];
var setNameById = function(id, newName) {
arrayOfObjects.forEach(function(obj) {
if(obj.id = id) obj.name = newName;
});
};
console.log(JSON.stringify(arrayOfObjects)); // initial array logged
setNameById(2, 'Charlie');
console.log(JSON.stringify(arrayOfObjects));

Categories

Resources