This may be a duplicate, but I'm not sure.
I have the following array:
[
{
id: "object1"
},
{
id: "object2"
},
{
id: "object3"
}
]
The trick is, the array is dynamic, and, therefore, the global IDs of this array objects vary. For example, array[1] in one case may be an object with id "object1", and, in other case, that with an id of "object3".
How to query this array based on the id string and have the array index as the output?
reduce into an object indexed by id, with the values being the index of that id's object in the original array, and then you can use simple object lookup:
const input = [
{
id: "object1"
},
{
id: "object2"
},
{
id: "object3"
}
];
const indexedById = input.reduce((a, { id }, i) => {
a[id] = i;
return a;
}, {});
console.log(indexedById.object2); // index of 1 in input
.findIndex is another possibility, but it has worse time complexity than object lookup.
Array has a findIndex, so you could do const findById = (x) => xs.findIndex(({ id }) => id === x) where x is your id string and xs is your array of objects.
Related
I have an array like ['A','B','F'] and an array of objects
[
{
name:'A',
prop1:'value1'
},
{
name:'C',
prop3:'value3'
},
{
name:'E',
prop7:'value7'
},
]
I want to filter out objects where name exists in array and add property exists:true to the array of objects and return the updated array of objects.
So for the above case it should return
[
{
name:'A',
prop1:'value1',
exists:true
},
{
name:'C',
prop3:'value3'
},
{
name:'E',
prop7:'value7'
},
]
I suppose it could be done with help of JavaScript Sets but not sure how. Also can this be done in linear complexity?
To achieve linear time complexity, you can turn your character array into a Set. Now just simply loop through the array of objects.
const characters = ['A','B','F'];
const objects = [
{
name:'A',
prop1:'value1'
},
{
name:'C',
prop3:'value3'
},
{
name:'E',
prop7:'value7'
},
];
const charSet = new Set(characters);
const output = objects.map(obj => {
if (charSet.has(obj.name)) obj.exists = true;
return obj;
});
This takes O(n + m), where n is the length of the character array, and m is the length of the object array.
Say that I had the following two arrays:
var arrToChangeAndCompare = [{name:'Bob'},{name:'Joe'},{name:'Alise'},{name:'Joe1'}];
var arrToCompare = [{name:'Frank'},{name:'Joe'},{name:'Jen'},{name:'Joe1'}];
And I want to first array to only contain unique names in the array its in, but also unique names compared to the second array (arrToCompare). To be clear, I don't want to REMOVE values that are not unique, I want to CHANGE them in "arrToChangeAndCompare" so they are then unique to both arrays. Keep in mind that if there are non-unique values in "arrToCompare", this does not matter. The only rule is that the "arrToChangeAndCompare" only has unique names in its array and names that are unique compared to "arrToCompare" as well.
I have the following code that almost does what I want, but it doesn't check the second array again once it changes a value in the first array to be unique, which results in the "arr" array to have all unique values, but the "arr" values are not unique in both arrays (Joe1 exists in the first array and the second array).
ALMOST WORKING CODE
var arr = [{name:'Bob'},{name:'Joe'},{name:'Alise'},{name:'Joe1'}];
var arr2 = [{name:'Frank'},{name:'Joe'},{name:'Jen'},{name:'Joe1'}];
var arr3;
arr2.forEach(e2 => {
arr3 = arr.map(e => {
var name = e.name.match(/[a-zA-Z]*/)[0]
if (e2.name === name) {
var number = e.name.match(/[0-9]+/)
if (number) {
e.name = name + (+number[0] + 1)
} else {
e.name = name + 1
}
}
return e
})
})
console.log(arr3)
The expected output of arrays listed at the top would be one array that looks like this:
[
{
"name": "Bob"
},
{
"name": "Joe2"
},
{
"name": "Alise"
},
{
"name": "Joe3"
}
]
EXPLANATION OF OUTPUT
Bob is unique, so no actual is done for the first object in arrToChangeAndCompare
Joe is not unique compared to the arrtoCompare, so its number needs to be changed. But, since Joe1 exists in arrToChangeAndCompare as well, it has to be incremented again to Joe2
Alise is unique to both arrays, so no actual is done for the third object in arrToChangeAndCompare
Joe1 is not unique compared to arrtoCompare, so Joe1 must be incremented to Joe2, But since Joe2 also exists in arrToChangeAndCompare, it must then be incremented to Joe3
All values in arrToChangeAndCompare are now unique compared to its own array and arrtoCompare
Please ask additional questions as needed. Your help is much appreciated!
You could take a Set with name and the letter parts of name and check against.
If not found add string to set and return the value.
If found take letters, digits and increment the numerical value until no more combined string is in the set. Then update the set and return the new string.
var array1 = [{ name: 'Bob', foo: 42 }, { name: 'Bob', bar: 42 }, { name: 'Bob' }, { name: 'Joe' }, { name: 'Joe' }, { name: 'Joe' }, { name: 'Alise' }, { name: 'Joe1' }],
array2 = [{ name: 'Frank' }, { name: 'Joe' }, { name: 'Jen' }, { name: 'Joe1' }],
items = array2.reduce((s, { name }) => s.add(name).add(name.match(/^\D+/)[0]), new Set),
result = array1.map(({ name, ...o }) => {
if (!items.has(name)) {
items.add(name);
return { name, ...o };
}
var [letters, digits = 0] = name.split(/(\d+)/);
digits = +digits;
while (items.has(letters + ++digits));
items.add(letters + digits);
return { name: letters + digits, ...o };
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Suppose,
i have an object with properties, details : {"name","id"} , now there is an array that holds collection of details. now suppose , an object with {name:max, id:55} is pushed in the array more than once. how do i find out the last entered {name:max,id:55} from that array using TypeScript .
You can do it with pure JavaScript and lastIndexOf:
const myArray = [{
name: "max",
id: 55
}, {
name: "john",
id: 13
}, {
name: "susan",
id: "123"
}, {
name: "max",
id: 55
}];
const lastEntered = (name, id) => {
var matches = myArray.filter(e => e.name == name && e.id == id);
return matches.length - 1;
}
console.log(lastEntered("max", 55));
Array is last in first out data structure.
So the last in element will occupy the element with the largest index.
So you may get the element by array[array.length-1]
You can use reduce to change the array to an object, where the key is a value from the object, and the value is the last index of that key.
const details = [{ name: 'max', id: 55 }];
const detailsMap = details.reduce((acc, person, index) => {
acc[person.id] = index;
return acc;
}, {});
const lastIndexOfMax = detailsMap[55];
Here we set the id from the detail object to the key (because I assumed that each id is unique). When we enter that key into the details map, it returns to use the index of the array where that id is last located.
I have bunch of array of object, I want to get particular object using filter, but I got array using below code.
const target = [{
name: 'abc',
id: 1
}, {
name: 'def',
id: 2
}]
const x = target.filter(o => o.id === 1)
console.log(x)
As said in the comments, filter won't allow you to get a particular object from an array - it just returns another array which elements satisfy the given predicate. What you actually need is Array.prototype.find(). Quoting the doc:
The find() method returns the value of the first element in the array
that satisfies the provided testing function. Otherwise undefined is
returned.
So your code looks like this:
const target = [{
name: 'abc',
id: 1
}, {
name: 'def',
id: 2
}];
const x = target.find(o => o.id === 1);
console.log(x); // {name: "abc", id: 1}
array.filter always return array. But you can try this-
const target = [{
name: 'abc',
id: 1
}, {
name: 'def',
id: 2
}]
let obj = {}
const x = target.filter( (o, index) => {
if(o.id === 1)
obj = target[index]
})
console.log(obj)
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
The find() method returns the value of the first element in the provided array that satisfies the provided testing function. If no values satisfy the testing function, undefined is returned.
Array.prototype.filter will return array containing elements from original array that passed test function.
If you are sure that id's are unique simply do x[0] to get result.
It's very easy just get first item in retrned as:
const target = [{name: 'abc', id: 1}, {name: 'def', id: 2}]
const x = target.filter(o => o.id === 1)
console.log(x[0])
I have array of object and I want to change into array an remove object.
My object is like:
[{ABC: "ELEMENT1", MAX: 2, MIN: "Yes"}, {ABC: "ELEMENT2", MAX: 1, MIN: "Yes"}]
and I want result like array with index:
[{"ELEMENT1",2,"Yes"},{"ELEMENT2",2,"Yes}]
Use Array#map over Object.keys(obj)
The Object.keys() method returns an array of a given object's own enumerable properties.
The map() method creates a new array with the results of calling a provided function on every element in this array.
var ip = {
STU: "Study1",
SUB: 2,
EXL: "Yes"
};
var op = Object.keys(ip).map(function(key) {
return ip[key];
});
console.log(op);
To iterate Array-of-Objects
var ip = [{
STU: "Study1",
SUB: 2,
EXL: "Yes"
}, {
STU: "Study2",
SUB: 4,
EXL: "No"
}];
var op = ip.map(function(item) {
return Object.keys(item).map(function(key) {
return item[key];
});
});
console.log(op);
That would be:
var array = Object.keys(obj).map(key => obj[key]);
However, order is not guaranteed for Object.keys as it works like a for-in loop, whose order of traversal is arbitrary. You may not get ["Study1",2,"Yes"] in that exact order. If you want to guarantee order, you must use an array containing the order of the keys and extract them from your object in that order.
var keyArray = ['STU', 'SUB', 'EXL'];
var array = keyArray.map(key => obj[key]);