I know how to grab array by its index. Also I know how to grab objects by its key, but I don't want to grab it by key.
Here you go for my objects
var x = {"email":["This Position"]}
And I know I can grab This Position like writing x.email[0].
But the problem is, I can't always grab the This Position with x.email[0].
Because the server sometimes sends me like this:
var x = {"phone":["This Position"]}
Even some time like this: var x = {"name":["This Position"]}
So you know to grab This Position not possible, because, for those variable, I have to write like x.phone[0] or x.name[0].
And it is very tough to write for hundred of variables.
var x = {"email":["This Position"]}
So I want to grab This Position not with like this x.email[0].
Can give you me a solution that whatever key name, I just want to grab first first value first key? Is it possible?
Use Object.values like so:
var x = {"email":["This Position"]};
const [[res]] = Object.values(x);
console.log(res);
You can use Object.values
var x = {"email":["This Position"]}
var value = Object.values(x)[0][0]
This is possible in implementations where JavaScript objects are ordered by insertion sequence. This answer along with the other answers in the thread offers a good overview of when you can rely on this and under what restrictions. The rest of this answer assumes ordering is guaranteed by the ES implementation.
The most direct solution is to use Object.values(obj)[0], Object.keys(obj)[0] or Object.entries(obj)[0]. However, these methods visit every entry in the object which results in O(n) time complexity, so these approaches are only valuable for simple use cases that aren't performance-critical.
const obj = {
foobar: ["This position"],
foobaz: ["That position"]
};
// succinct but linear:
console.log(Object.keys(obj)[0]);
console.log(Object.values(obj)[0]);
console.log(Object.entries(obj)[0]);
// since you want the first array element of the first value, use:
console.log(Object.values(obj)[0][0]);
Faster is to iterate over the keys with in and return the first. This requires a bit more code but offers a massive complexity improvement for large objects.
// use a loop and return after the first element, O(1):
const getFirstVal = obj => {
for (const k in obj) return obj[k];
};
const getFirstKey = obj => {
for (const k in obj) return k;
};
const getFirstEntry = obj => {
for (const k in obj) return [k, obj[k]];
};
const obj = {
foobar: ["This position"],
foobaz: ["That position"]
};
console.log(getFirstVal(obj));
console.log(getFirstKey(obj));
console.log(getFirstEntry(obj));
A general solution to the "first n entries" problem is to create a generator version of Object.entries. You can use the generator to step through the object's entries, only going as far as you need and as you need it.
The downside is that there's a bit of generator management for the caller, but this can be abstracted with a function. Use this for cases when you anticipate that you might need more than just the first entry in performance-critical code.
// use a generator function for maximum flexibility
function *iterEntries(obj) {
for (const k in obj) yield [k, obj[k]];
}
const firstEntries = (obj, n=1) => {
const gen = iterEntries(obj);
return Array(n).fill().map(_ => gen.next().value);
};
/* warning: linear search */
const entryAtIndex = (obj, i) => {
const gen = iterEntries(obj);
while (i--) gen.next();
return gen.next().value;
};
const obj = Object.fromEntries(
Array(26).fill().map((_, i) => [String.fromCharCode(i + 65), i])
);
console.log(iterEntries(obj).next().value);
console.log(firstEntries(obj, 4));
console.log(entryAtIndex(obj, 4));
You can make versions specific to values or keys as desired. As shown, this technique is also effective for "indexing" into the n-th key of an ordered object. If you find you're doing this frequently, though, consider using an array instead of (or alongside of) an object which is the correct data structure for random index access.
Related
How to take out common array from array of object.
I have object of arrays.
var myObj = {
0 : [{"result":"AC","id":847}]
1 : [{"result":"AC","id":847},{"result":"BC","id":852}],
2 : ["result":"AC","id":847}],
3 : [{"result":"AC","id":847}]}
In this case I have {"result":"AC","id":847} is common in all array element,
how tocompare and print only common element across the array inside myObj
Here is what I am trying.
In the first place, the Object is not the best option for collections, if you can change I recommend you to use Array.
In this case with your Object you can do something like:
Object.keys(myObj).map(key=>{
// here you have one by one each a key of the object
// myObj[key] will have the array
})
in the case of numbers of arrays are always the same you can destruct your object:
const [1,2,3,4,5] = myObj;
then each of them will be available as a const in your scope.
To answer your question:
const fullCollection = [];
let common = {};
let occurrences = 0;
Object.keys(myObj).map(key=>{
// here you have one by one each a key of the object
// myObj[key] will have the array
myObj[key].map(el=>{
fullCollection.push(el);
});
})
fullCollection.forEach(obj1={
let temp = fullCollection.filter((obj) => JSON.encode(obj1) === JSON.encode(obj2));
if(temp.length > occurences){
common = temp[0];
occurences = temp.length;
}
});
console.log('the most common object is: ', common, 'with :', occurrences, 'occurrences');
Note: I couldn't test it, but this may give you an idea of how to solve your problem.
Note2: I use JSON.encode to compare objects but you're free to use the way you want.
Method 1 is using an array which contains objects and i want to get an object with a certain ID.
The second method is suing map, in which an object is created at "id" key.
To get object from array
array.findIndex((x) => x.id == id)
and to get object from map is simple
Map.get(id)
I want to know which method is faster and better
Big O notation is how long an algorithm takes to execute depending on how
long is the input and usually talking about the unfavorable case scenario.
When you use array.findIndex((x) => x.id == id), it means that the whole array should be iterated in the worst case array.length times. So the complexity of this method is O(n).
When you use Map.get(id), it means that hash will be calculated and then by this hash we can go to the desired item in Map. So the complexity of this method is O(1). It is faster.
UPDATE:
Comment by VLAZ:
On the flip side, of course, a map takes extra space and processing.
So, if you only want to look up one or two items, it's probably not
worth it. However, if you have lots of lookups, it will have a massive
benefit speed-wise. Just throwing it out there. I'd personally opt for
a Map.
It Depends
In theory you should use Big O notation to decide. As noted, .findIndex is O(n) while map.get is O(1), which simply means map.get is more efficient. However, in practice, there are many other considerations. For example:
What is the the size of the data? Does it comes already as an array and you need to Map it? How many lookups you need to perform?
On a very small array, simple lookup (for loop, not .findIndex, because of the additional function call) might be more efficient. On very large array, mapping takes time, few lookups will be more efficient than mapping.
Consider the following code, for large size array, two lookups, mapping will be highly inefficient. Only above ~15-20 lookups (depend on your CPU, memory speed, ETC), mapping will be more efficient.
'use strict';
const gen_arr = size => {
const arr = [];
while (size) {
arr.push({ id:size, data:size.toString() });
--size;
}
return arr;
};
const map_it = arr => {
const map = new Map();
for (let obj of arr) {
map.set(obj.id, obj);
}
return map;
}
// Assume nodejs if no performance
const perf = typeof performance != 'undefined' ? performance : { now: ()=> Number(process.hrtime.bigint() / 1000000n) };
let t = perf.now();
const timeit = msg => { const t1 = perf.now(); console.log(msg, 'took', t1 - t, 'ms'); t = t1; };
const start_timer = () => t = perf.now();
const arr_size = 1000000;
const arr = gen_arr(arr_size);
start_timer();
let r = arr.find(obj => obj.id === 1); // end
timeit(`finding ${JSON.stringify(r)} in array`);
r = arr.find(obj => obj.id === arr_size);
timeit(`finding ${JSON.stringify(r)} in array`);
let map = map_it(arr);
timeit('mapping');
r = map.get(1);
timeit(`finding ${JSON.stringify(r)} in map`);
r = map.get(arr_size);
timeit(`finding ${JSON.stringify(r)} in map`);
I want to filter a array by keeping the same array without creating a new one.
with Array.filter() :
getFiltersConfig() {
return this.config.filter((topLevelConfig) => topLevelConfig.name !== 'origin')
}
what is the best way to get the same result by filtering by value without returning a new array ?
For completeness, I thought it might make sense to show a mutated array variant.
Below is a snippet with a simple function mutationFilter, this will filter the array directly, notice in this function the loop goes in reverse, this is a technique for deleting items with a mutated array.
Also a couple of tests to show how Array.filter creates a new array, and mutationFilter does not.
Although in most cases creating a new array with Array.filter is normally what you want. One advantage of using a mutated array, is that you can pass the array by reference, without you would need to wrap the array inside another object. Another advantage of course is memory, if your array was huge, inline filtering would take less memory.
let arr = ['a','b','a'];
let ref = arr; //keep reference of original arr
function mutationFilter(arr, cb) {
for (let l = arr.length - 1; l >= 0; l -= 1) {
if (!cb(arr[l])) arr.splice(l, 1);
}
}
const cond = x => x !== 'a';
const filtered = arr.filter(cond);
mutationFilter(arr, cond);
console.log(`ref === array -> ${ref === arr}`);
console.log(arr);
console.log(`ref === filtered -> ${ref === filtered}`);
console.log(filtered);
I want to filter a array by keeping the same array without creating a new one.
what is the best way to get the same result by filtering by value without returning a new array ?
I have an answer for the second criterion, but violates the first. I suspect that you may want to "not create a new one" specifically because you only want to preserve the reference to the array, not because you don't want to create a new array, necessarily (e.g. for memory concerns).
What you could do is create a temp array of what you want
var temp = this.config.filter((topLevelConfig) => topLevelConfig.name !== 'origin')
Then set the length of the original array to 0 and push.apply() the values "in-place"
this.config.length = 0; //clears the array
this.config.push.apply(this.config, temp); //adds what you want to the array of the same reference
You could define you custom method like so:
if(!Array.prototype.filterThis){
Array.prototype.filterThis = function (callBack){
if(typeof callBack !== 'function')
throw new TypeError('Argument must of type <function>');
let t = [...this];
this.length = 0;
for(let e of t) if(callBack(e)) this.push(e);
return this;
}
}
let a = [1,2,3,4,5,5,1,5];
a.filterThis(x=>x!=5);
console.log(a);
Warning: Be very cautious in altering built in prototypes. I would even say unless your making a polyfill don't touch. The errors it can cause can be very subtle and very hard to debug.
Not sure why would you want to do mutation but if you really want to do it, maybe assign it back to itself?
let arr = ['a','b','a'];
arr = arr.filter(x => x !== 'a');
console.log(arr)
I am creating an object with dynamic keys as seen here:
const myObject = [
{PINO: 1764},
{FANH: 2737},
{WQTR: 1268},
{CICO: 1228}
];
I want to get the key and value with the lowest value, in this case it's {CICO: 1228}.
How I create this object is like so:
let basic = [];
_.map(values, value => {
let result = value[Object.keys(value)].reduce((c, v) => {
// sum up the amounts per key
c[Object.keys(value)] = (c[Object.keys(value)] || 0) + parseInt(v.amount);
return c;
}, {});
basic.push(result);
})
console.log(basic) => [{PINO: 1764}, {FANH: 2737}, {WQTR: 1268}, {CICO: 1228}]
How can I get the lowest number with it's key from the basic object? I tried using sort and taking the lowest number but the keys are created dynamically so I don't think I have anything I can sort against.
This is a pretty inconvenient way to store data since the keys are more-or-less useless and you need to look at the values of each object to do anything. But you can do it if you need to with something like:
const myObject = [
{PINO: 1764},
{FANH: 2737},
{WQTR: 1268},
{CICO: 1228}
];
let least = myObject.reduce((least, current) => Object.values(least)[0] < Object.values(current)[0] ? least : current)
console.log(least)
If it was a large list, you might benefit from converting the array to a different format so you don't need to keep creating the Object.values array.
Iterate the array with Array.reduce(), get the values of the objects via Object.values(), and take the one with the lower number:
const myObject = [
{PINO: 1764},
{FANH: 2737},
{WQTR: 1268},
{CICO: 1228}
];
const result = myObject.reduce((r, o) =>
Object.values(o)[0] < Object.values(r)[0] ? o : r
);
console.log(result);
I am trying to solve a problem which states to remove(delete) the smallest number in an array without the order of the elements to the left of the smallest element getting changed . My code is -:
function removeSmallest(numbers){
var x = Math.min.apply(null,numbers);
var y = numbers.indexOf(x);
numbers.splice(y,1);
return numbers;
}
It is strictly given in the instructions not to mutate the original array/list. But I am getting an error stating that you have mutated original array/list .
How do I remove the error?
Listen Do not use SPLICE here. There is great known mistake rookies and expert do when they use splice and slice interchangeably without keeping the effects in mind.
SPLICE will mutate original array while SLICE will shallow copy the original array and return the portion of array upon given conditions.
Here Slice will create a new array
const slicedArray = numbers.slice()
const result = slicedArray.splice(y,1);
and You get the result without mutating original array.
first create a copy of the array using slice, then splice that
function removeSmallest(numbers){
var x = Math.min.apply(null,numbers);
var y = numbers.indexOf(x);
return numbers.slice().splice(y,1);
}
You can create a shallow copy of the array to avoid mutation.
function removeSmallest(numbers){
const newNumbers = [...numbers];
var x = Math.min.apply(null,newNumbers);
var y = newNumbers.indexOf(x);
newNumbers.splice(y,1);
return newNumbers;
}
array.slice() and [... array] will make a shallow copy of your array object.
"shallow" the word says itself.
in my opinion, for copying your array object the solution is:
var array_copy = copy(array);
// copy function
function copy(object) {
var output, value, key;
output = Array.isArray(object) ? [] : {};
for (key in object) {
value = object[key];
output[key] = (typeof value === "object") ? copy(value) : value;
}
return output;
}
Update
Alternative solution is:-
var arr_copy = JSON.parse(JSON.stringify(arr));
I'm not sure what the exact context of the problem is, but the goal might be to learn to write pure transformations of data, rather than to learn how to copy arrays. If this is the case, using splice after making a throwaway copy of the array might not cut it.
An approach that mutates neither the original array nor a copy of it might look like this: determine the index of the minimum element of an array, then return the concatenation of the two sublists to the right and left of that point:
const minIndex = arr =>
arr.reduce(
(p, c, i) => (p === undefined ? i : c < arr[p] ? i : p),
undefined
);
const removeMin = arr => {
const i = minIndex(arr);
return minIndex === undefined
? arr
: [...arr.slice(0, i), ...arr.slice(i + 1)];
};
console.log(removeMin([1, 5, 6, 0, 11]));
Let's focus on how to avoid mutating. (I hope when you say "remove an error" you don't mean "suppress the error message" or something like that)
There are many different methods on Array.prototype and most don't mutate the array but return a new Array as a result. say .map, .slice, .filter, .reduce
Telling the truth just a few mutate (like .splice)
So depending on what your additional requirements are you may find, say .filter useful
let newArray = oldArray.filter(el => el !== minimalElementValue);
or .map
let newArray = oldArray.map(el => el === minimalElementValue? undefined: el);
For sure, they are not equal but both don't mutate the original variable