Remove all keys that have the same value in array - javascript

I need to remove all keys except last inserted that have the same value on key id_ask in array but I'm learning javascript and I still do not know how to do this.
jQuery(function()
{
let arr = []
let q = []
$("body").on('click', '.link_resposta', function(event)
{
event.preventDefault();
/* Act on the event */
let id_poll = $(this).data("idpesquisa")
let id_ask = $(this).data("idpergunta")
let id_anwser = $(this).children("li").data("idresposta")
let q = {
id_poll,
id_ask,
id_anwser
}
arr.push(q)
console.log(arr)
});
});

Using a combination of Set, Array.reverse() and Array.map we can solve this easily.
We first use the Set and we map our source array in, just feeding the id_ask field. From that we get an array of unique id_ask.
We then map the unique id_ask array and for each id_ask we call a find() on the source array in reverse.
Comments inline.
const sampleArray = [
{
id: 1,
id_ask: 2,
id_answer: 3
},
{
id: 2,
id_ask: 2,
id_answer: 5
},
{
id: 3,
id_ask: 3,
id_answer: 3
},
{
id: 4,
id_ask: 3,
id_answer: 1
},
{
id: 5,
id_ask: 4,
id_answer: 3
}
];
// Create a unique Set of Ask ID
const uniqueAskId = [...new Set(sampleArray.map(e => e.id_ask))];
console.log(uniqueAskId);
// Use Map and Reverse to get last item.
const r = uniqueAskId.map(uid => sampleArray.reverse().find(ask => ask.id_ask === uid));
console.log(r);
Here it is as a single statement:
const sampleArray = [
{
id: 1,
id_ask: 2,
id_answer: 3
},
{
id: 2,
id_ask: 2,
id_answer: 5
},
{
id: 3,
id_ask: 3,
id_answer: 3
},
{
id: 4,
id_ask: 3,
id_answer: 1
},
{
id: 5,
id_ask: 4,
id_answer: 3
}
];
// put together in a single statement.
const result = [...new Set(sampleArray.map(e => e.id_ask))]
.map(uid => sampleArray.reverse().find(ask => ask.id_ask === uid));
console.log(result);
NOTE: For large datasets it would obviously be more efficient to call the reverse() one time before you use.
const revArray = myArray.reverse();
const resultArray = [...new Set(revArray.map(e => e.id_ask))]
.map(uid => revArray.reverse().find(ask => ask.id_ask === uid));

Related

Value change in 1 object changes in all objects in array

I have an array of objects. Each object has a key quantity and value. I want to duplicate each object in the array based on its quantity. Next, I want to manipulate only one of the duplicated object in the array. But on manipulating value of 1 object, value of all duplicated objects change. Here is my code:
let arr = [
{ id: 1, quantity: 3, value: 10 },
{ id: 2, quantity: 1, value: 5 },
{ id: 2, quantity: 5, value: 5 },
];
const newArr = [];
for (const a of arr) {
if (a.quantity > 1) {
let quantity = a.quantity;
a.quantity = 1;
while (quantity--) {
newArr.push(a);
}
}
}
arr = newArr;
arr[0].value = 1;
When I changed the value of arr[0] to 1, value field of arr[1] and arr[2] also changed to 1.
I have tried copying the object using spread operator and JSON.parse(JSON.parse()), but none has worked.
Because newArr.push(a) .a push to newArr ref to element of arr
You can edit same as :
let arr = [
{ id: 1, quantity: 3, value: 10 },
{ id: 2, quantity: 1, value: 5 },
{ id: 2, quantity: 5, value: 5 },
]
const newArr = []
for (const a of arr) {
if (a.quantity > 1) {
let quantity = a.quantity;
a.quantity = 1;
while (quantity--) {
newArr.push({...a})
}
}
}
arr = [...newArr]
arr[0].value = 1
console.log(arr)
// example for Memory Management
let a = { id: 1, quantity: 3, value: 10 }
let b = { id: 1, quantity: 3, value: 10 }
let c = arr[0]
let d = {...arr[0]}
console.log(a === arr[0]) // false : different allocates memory for contain value
console.log(a === b) // false : different allocates memory for contain value
console.log(c === arr[0]) // true : refer to a memory
console.log(d === arr[0]) // false : different allocates memory for contain value

Dynamic conditions of array for javascript

const conditionalArray = [
{ name: "line", condition: ">=", value: 5 },
{ name: "revene", condition: "in", value: 6 },
];
const dataTofilter = [
{ line: 3, revene: 4, sale: 3, fridge: "lg" },
{ line: 6, revene: 3, sale: 2, fridge: "samsung" },
];
I have these 2 arrays one is having conditions ( many more can be there) and second is to filter
Final result should be [{ line: 6, revene: 3, sale: 2, fridge: "samsung" }]
Something along the lines of:
const conditionalArray = [
{ name: "line", condition: ">=", value: 5 },
{ name: "revene", condition: "<", value: 6 },
];
const dataTofilter = [
{ line: 3, revene: 4, sale: 3, fridge: "lg" },
{ line: 6, revene: 3, sale: 2, fridge: "samsung" },
];
const conditions = {
'<': (x, y) => x < y,
'<=': (x, y) => x <= y,
'>': (x, y) => x > y,
'>=': (x, y) => x >= y,
};
const result = dataTofilter.filter(data => {
for (const el of conditionalArray) {
if (!conditions[el.condition](data[el.name], el.value)) {
return false;
}
}
return true;
});
console.log(result);
const newData = dataTofilter.filter((item) => {
const passedConditions = [];
conditionalArray.forEach((cond) => {
switch(cond.condition){
case ">":
passedCondition.push(item[cond.name] > cond.value);
break;
case ..... //other conditional checks
}
}); //end forEach
return Arrays.asList(passedCondition).contains(false) === false;
});
If you don't want to use eval you can do something like this. We loop through all the data first and use filter to only return values that pass our conditional check.
We then loop trough the conditional array testing each condition on the single item and save the value to passedConditions. You will need to add the rest of the conditions.
Finally we return wether the passedCondtions array did not contain a false value. This would mean we passed all the conditional checks.
I'm really not a big fan of it. But I don't see another way as eval() to make the condition work as an actual operator without doing plenty of manual checks. Also the following solution assumes that every item in dataToFilter has a corresponding item in conditionalArray.
const conditionalArray = [
{ name: "line", condition: ">=", value: 5 },
{ name: "revene", condition: "<", value: 6 },
];
const dataTofilter = [
{ line: 3, revene: 4, sale: 3, fridge: "lg" },
{ line: 6, revene: 3, sale: 2, fridge: "samsung" },
];
const result = dataTofilter.filter((item, i) =>
eval(
`${item[conditionalArray[i].name]}${conditionalArray[i].condition}${
conditionalArray[i].value
}`
)
);
console.log(result);

for loop inside array filter method [duplicate]

This question already has an answer here:
trying to use a for loop with if else statement in objects
(1 answer)
Closed 1 year ago.
Let say I have two arrays
From here I want to filter arr1 with arr2 condition (assuming arr2 = arr1 id).
I have tried this code but only return first condition.
const arr1 = [{
id: 1,
name: "Jhon"
},
{
id: 2,
name: "Barbara"
},
{
id: 3,
name: "Rio"
}
];
const arr2 = [1, 2, 5];
const filter = (arr1, arr2) => {
const output = arr1.filter(value => {
for (let i = 0; i < arr2.length; i++) {
if (value.id !== arr2[i]) {
return false;
}
return true;
}
})
console.log(output);
};
filter(arr1, arr2);
// output = [{id: 1, name: "Jhon"}]
// intended output [{id: 1, name: "Jhon"}, {id: 2, name: "Barbara}]
Anyone can tell me what I'm missing? Thank you
See the dupe why it did not work and then vastly simplify this
const arr1 = [{ id: 1, name: "Jhon" }, { id: 2, name: "Barbara" }, { id: 3, name: "Rio" } ];
const arr2 = [1, 2, 5];
const filter = (arr1, arr2) => arr1.filter(({id}) => arr2.includes(id))
console.log(filter(arr1,arr2))

How to filter an Array with another Array

I have an Array of Objects:
const array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }]
I have a second array containing the ID's that I want to filter out of the first Array:
const ids = [1, 2]
How do I create a new Array of Objects without the ID's found in ids.
This is a fairly simple filter operation
const array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }];
const ids = [1, 2];
var result = array.filter( x => !ids.includes(x.id));
console.log(result);
If you need to mutate the original array you can do like this:
const array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }];
const ids = [1, 2];
ids.forEach(idToDelete => {
const index = array.findIndex(({ id }) => id === idToDelete);
array.splice(index, 1);
});
console.log(array);
If you need a new array you can do like this:
const array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }];
const ids = [1, 2];
const result = array.filter(({ id }) => !ids.includes(id));
console.log(result);
You could also reassign a new array to the array variable:
let array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }];
const ids = [1, 2];
array = array.filter(({ id }) => !ids.includes(id));
console.log(array);
Use Array.filter :
let array = [
{id: 1, bar: "test" },
{id: 2, bar: "test2" },
{id: 3, bar: "test3" }
];
let ids = [1,2];
let filteredArray = array.filter(row=>!ids.includes(row.id));
console.log(filteredArray);
Use this oneliner from lodash.
const _ = require("lodash");
let filteredArray = _.remove(array, el=>[1,2].includes(el.id))
Use filter and indexOf.
const arr = [{ id: 1, bar: 'test' }, { id: 2, bar: 'test2' }, { id: 3, bar: 'test3' }];
const ids = [1, 2];
const result = arr.filter(element => ids.indexOf(element.id) === -1);
console.log(result);
We can filter an array in JavaScript using Array filter()
const myArray = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }]
const ids = [1,2]
const resultArray = myArray.filter(item => !ids.includes(item.id));
console.log(resultArray);
In term of performance the best solution will be the next one:
let array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }];
const ids = [1,2];
const idSet = new Set();
for (const id of ids) {
idSet.add(id);
}
array = array.filter(x => !set.has(x.id));
//const newArray if you need the initial array unmodified
In this case we perform two consequencial iteration instead of a nested one, so the time complexity will be O(n) instead of O(n^2);
##Edit
If you instead need the initial array to be mutated and not overwritten you can use this approach:
const ids = [1,2];
const array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }];
for (const id of ids) {
const index = array.findIndex(x => x.id == id);
array.splice(index, 1);
}
In the second case the time complexity will be O(n*m), where n is array length and m is ids length.
I want to propose something wildly different.
In my case, I wanted to filter one list of unique IDs against another.
I was curious if regex could do it faster.
Such a method really only works with one-dimensional arrays of simple objects.
It's probably best if items a single regex 'word' (string of 0-9a-z_).
A list of ids works perfect.
array.filter works best on small datasets (1,000), usually slightly faster
regex worked 66% faster on large datasets (10,000)
regex speed advantage widens. 90% faster on 100,000.
On comparing two arrays of 1m items, filter didn't do anything for me after more than 90 seconds. Regex returned a result in six seconds.
In this case, the input is number[], and the output is string[], which works for my purposes, but you can use map to convert back to numbers if you need, .
var listlength = 10000;
function createArray() {
let arr = new Set();
for (let i = 0; i < listlength; i++) {
arr.add(Math.floor(Math.random() * listlength));
}
return arr;
}
function filter() {
let arr1 = Array.from(createArray());
let arr2 = Array.from(createArray());
let start = +new Date();
let arr3 = arr1.filter((n) => !arr2.includes(n));
console.log('filter', (+new Date() - start) + 'ms', arr1.length, arr2.length, arr3.length);
}
function regex() {
let arr1 = Array.from(createArray());
let arr2 = Array.from(createArray());
let start = +new Date();
let str1 = arr1.join(',') + ',';
str1 = str1.replace(new RegExp('\\b(' + arr2.join('|') + '),', 'g'), '');
let result = str1.split(',') // .map(e=>Number(e)); (to convert back to number[])
result.pop();
console.log('regex', (+new Date() - start) + 'ms', arr1.length, arr2.length, result.length);
}
for (let x = 0; x < 10; x++) {
console.log(`try ${x}`);
filter();
regex();
}
On my NodeJS app, sets of 100,000, regex more than 90% faster.

Check if variables are equal to each other

I was wondering how you can check if variables are equal to each other. I have around 10 variables and I want to check if some of them are equal to each other, and if they are they should be in their own array
const user1TeamID = 2
const user2TeamID = 4
const user3TeamID = 2
const user4TeamID = 3
const user5TeamID = 1
const user6TeamID = 3
const user7TeamID = 4 ... so on
EDIT:
So I have 10 users that have a team, and I want to filter all users into their teams ID, so my output is an array
How can I do that?
I think you have to rearrange your declaration. Instead of storing teamID at a variable with a userID prefix, you should use an array of objects for storing your data. You can follow this structure.
const teams = [
{
teamID: 1,
users: [1, 2, 4]
},
{
teamID: 2,
users: [3, 5, 7]
},
{
teamID: 3,
users: [6, 9]
},
...
]
first of all you have to learn about arrays and objects in javascript, there are planty of things you can do with them and they make things easy from the API to the front
if I were you I will do like this
1st- make an object containing all all your variables (users)
2nd- get all the unique teamIDs (teams)
3rd- group the users by the team
something like that
//those are the users
let users = [
{
userID: 1,
teamID: 2
},
{
userID: 2,
teamID: 4
},
{
userID: 3,
teamID: 2
},
{
userID: 4,
teamID: 3
},
{
userID: 5,
teamID: 1
},
{
userID: 6,
teamID: 3
},
{
userID: 7,
teamID: 4
},
]
//those are the teamListId
let teamListId = [...new Set(users.map(user => user.teamID))]
//grouped users by team
teamListId.map(teamID => ({
teamID,
users: users.filter(user => user.teamID == teamID).map(el => el.userID)
})
That could be simply as folowing:
const __get = (name) => { return eval(name) };
const idList = {};
for (let i = 1; i <= 10; i++) {
const name = `user${i}TeamID`, id = __get(name);
if (idList[id] === undefined) idList[id] = [];
idList[id].push(name);
}
console.log(idList);
for array type output:
const __get = (name) => { return eval(name) };
const idxList = {}, idArray = [];
for (let i = 1; i <= 10; i++) {
const name = `user${i}TeamID`, id = __get(name), index = idArray.length-1;
if (idxList[id]) {
index = idxList[id];
idArray[index][id].push(name);
} else {
idxList[id] = ++index;
idArray.push({});
idArray[index][id] = [name];
}
}
console.log(idArray);

Categories

Resources