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

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);

Related

Get last item active name on the list

How can i have the last item on the list where the case it is success?
children: [
{
case: "no-success",
name: "bruno",
endOffset: 5
},
{
case: "no-success",
name: "pippo",
endOffset: 5
}
{
case: "success",
name: "jo",
endOffset: 5
},
{
case: "success",
name: "Matteo",
endOffset: 5
},
{
case: "np-success",
name: "Robert",
endOffset: 5
}
]
I need to have the item where the name is Matteo.
Example for have the first i do : var foundIdx = this.newListWords[i].children.find(item => item.case === 'success').
Definition:
The find() method returns the FIRST element in the provided array that
satisfies the provided testing function. If no values satisfy the
testing function, undefined is returned.
You can reverse array:
this.newListWords[i].children.reverse().find(item => item.case === 'success')
Or you can use filter and get last child
const filtered = this.newListWords[i].children.filter(item => item.case === 'success')
const lastFind = filtered[filtered.length-1]
function lastSuccess(list: any[]): any {
const SUCCESS_STRING = 'success';
const [lastItem] = list // Take the list's head
.filter(o => o.success === SUCCESS_STRING) // Filter for success
.reverse(); // Reverse the list
return lastItem;
}
const item = lastSuccess(this.newListWords[i].children);
var children = [
{
case: "no-success",
name: "bruno",
endOffset: 5
},
{
case: "no-success",
name: "pippo",
endOffset: 5
},
{
case: "success",
name: "jo",
endOffset: 5
},
{
case: "success",
name: "Matteo",
endOffset: 5
},
{
case: "np-success",
name: "Robert",
endOffset: 5
}
];
function getLastSuccess(children) {
if (!Array.isArray(children)) {
return {};
}
for (var i = children.length - 1, o; o = children[i]; i--) {
if (o.case === 'success') {
return o;
}
}
}
console.log(getLastSuccess(children));
Single line code
let v = children.reduce((s, c) => { if (c.case === "success") { return c } else { return s } }, null);
You will get null if there is no success.
This should find the last item in the filtered array with 'success',
children.findLast(item => item.case === 'success')

function to Get array and specific start letter and end letter and then return a list of names that starts and end with them

I have a long array of objects. I want to write a function to find for example names that start with specific letter and end with another specific letter and return a list of names that starts and end with them.
I tried some solutions but did not get answer.
Here I use a simple list: and I want a list that name start with "A" and end with "i" or any other case
myList = [{name: "Aji",family: "Ziansi"}, { name: "Alex", family: "ortega"}, {name:"Amandi",family: "Sedirini"}];
Output should be like this:
desiredLiset = [{name: "Aji",family: "Ziansi"}, {name:"Amandi",family: "Sedirini"}];
just in function declaration method.
Any solutions would be appreciated.
We can use Array.filter()
const myList = [{
name: "Aji",
family: "Ziansi"
}, {
name: "Alex",
family: "ortega"
}, {
name: "Amandi",
family: "Sedirini"
}];
const filterList = (list, start, end) => {
return list.filter(obj => {
const name = obj.name;
return name[0] === start && name[name.length - 1] === end;
});
};
const filtered = filterList(myList, "A", "i");
console.log(filtered);
You can use .filter() to get a list of the names you want:
myList = [{name: "Aji",family: "Ziansi"}, { name: "Alex", family: "ortega"}, {name:"Amandi",family: "Sedirini"}];
let desiredLiset = myList.filter(function(n){
return n.name.match(/^A.*i$/i) // Names that begin with 'A' and end with 'i'
});
console.log(desiredLiset)
// 0: Object { name: "Aji", family: "Ziansi" }
// ​1: Object { name: "Amandi", family: "Sedirini" }
Try this:
myList = [{name: "Aji",family: "Ziansi"}, { name: "Alex", family: "ortega"}, {name:"Amandi",family: "Sedirini"}];
const start='A'
const end='i'
const startEndRE = new RegExp(`^${start}.*${end}$`)
myList.filter(item=>(
startEndRE.test(item.name)
))
// Result
// [
// { name: 'Aji', family: 'Ziansi' },
// { name: 'Amandi', family: 'Sedirini' }
// ]
It is also possible to do using endsWith() and startsWith()
try:
const myList = [{ name: "Aji", family: "Ziansi" }, { name: "Alex", family: "ortega" }, { name: "Amandi", family: "Sedirini" }];
const newlist = myList.filter((obj) => obj.name.startsWith('A') && obj.name.endsWith('i'));
console.log(newlist);

Remove entire key when matched with matched array values

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)

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);

Find duplicate values by key from array of objects in Javascript

I know this question was answered before multiple times.
but i didn't find any solution that helped me out.
I got an array of objects with a Name property. I only want to get the objects with the same name.
How my Array looks like:
[
{
Name: 'test',
coolProperty: 'yeahCool1'
},
{
Name: 'test1',
coolProperty: 'yeahCool2'
},
{
Name: 'test2',
coolProperty: 'yeahCool3'
},
{
Name: 'test3',
coolProperty: 'yeahCool4'
},
{
Name: 'test',
coolProperty: 'yeahCool5'
}
]
so I only want to get:
[
{
Name: 'test',
coolProperty: 'yeahCool1'
},
{
Name: 'test',
coolProperty: 'yeahCool5'
}
]
I hope someone can help me out :)
For an O(N) solution, first reduce the array into an object that counts the number of occurrences of each name, and then filter the input by the occurrence count being 2:
const arr = [
{
Name: 'test',
coolProperty: 'yeahCool1'
},
{
Name: 'test1',
coolProperty: 'yeahCool2'
},
{
Name: 'test2',
coolProperty: 'yeahCool3'
},
{
Name: 'test3',
coolProperty: 'yeahCool4'
},
{
Name: 'test',
coolProperty: 'yeahCool5'
}
];
const counts = arr.reduce((a, { Name }) => {
a[Name] = (a[Name] || 0) + 1;
return a;
}, {});
console.log(arr.filter(({ Name }) => counts[Name] === 2));
You could use reduce() and filter() method to get the required result.
Using filter() method you need to check if length is greater than 2 then need it will be push in new array inside of reduce() method
DEMO
const arr =[{"Name":"test","coolProperty":"yeahCool1"},{"Name":"test1","coolProperty":"yeahCool2"},{"Name":"test2","coolProperty":"yeahCool3"},{"Name":"test3","coolProperty":"yeahCool4"},{"Name":"test","coolProperty":"yeahCool5"}];
let getCount = (name)=>{
return arr.filter(o => o.Name == name).length;
}
console.log(arr.reduce((r,item) => {
let len = getCount(item.Name);
return r.concat(len>1?item:[]);
}, []));
I see that you have already got an answer. So I thought of adding another way using map.
var counts = {};
var repeats = {};
arr.map(i => {
counts[i['Name']] = (counts[i['Name']] || []);
counts[i['Name']].push(i);
if (counts[i['Name']].length > 1) {
repeats[i['Name']] = counts[i['Name']];
}
});
console.log(repeats);
Not the best solution considering the performance. Just wanted to add an alternative method.
Hope it helps!!

Categories

Resources