Avoid using Object.values - javascript

df is an array of objects
I want to simplify this code, maybe the usage of Object.values could be redundant if I use another thing than map
Object.values(df.map(o => o.prop))
This piece of code returns an array of props.
Is it possible?

Unless df is a sparse array, the Object.values is totally redundant indeed.
df.map(o => o.prop)
already returns the same value as
Object.values(df.map(o => o.prop))

Related

best way to flatten n-level array into 2d array

I know there are a lot of ways to flatten an array in javascript, but I want to know what's the best way to flatten an n-level array into a 2D array
Input array looks like this : [[[[1,2]]],[2,3]] i need to convert this into [[1,2],[2,3]]
I tried using array.flat() but it flattens only 1 step and I also tried array.flat(Infinity) but it flattens the whole array into 1D array
the problem is am not sure how deeply nested my input array is. I could think of iterating recursively but am looking if js has any optimised&ready-made way of achieving this?
You could combine map and flat(Infinity) methods to flatten each sub-array to 1D.
const flatDeep = data => data.map(e => e.flat(Infinity))
console.log(flatDeep([[[[1,2]]],[2,3]]))
console.log(flatDeep([[[[1,2]]],[2,[[[3, [4]]]]]]))
Iterate the array and then use Array.flat(Infinity) method.
const list = [[[[1,2]]],[2,3],[[3,4]]]
const result = [];
for (value of list) {
result.push(value.flat(Infinity));
}
console.log(result);

cloning a 2d array using JSON.stringify()

How are 2d arrays cloned using json.stringify and json.pasrse ?I came across this function which does but couldn't get the technique.What are some other methods to achieve the same?
Note: The JSON.stringify() method converts a JavaScript value to a JSON string.
let g2 = arrayclone(this.state.gridfull);// note gridfull is 2d array
function arrayclone(arr) {
return JSON.parse(JSON.stringify(arr));
}
You could use ES6 deestructurtig:
[...arr]
Or you could you Array.from:
Array.from(arr)
Or you could use concat:
[].concat(arr)
Or you could use slice:
arr.slice()
arr.slice(0)
You could create an empty array and iterate over your original one pushing elements to the new one.
I think that's pretty much it.
Hope it helps.

Javascript filter function - Trying to understand it properly

I'd like some help to clarify how exactly I should be using filter.
The following works just fine:
let nums = [10, 12, 15, 20]
nums.filter(num => num > 14)
result = [15, 20]
If I understand this correctly, I'm passing in a function with num as argument.
Now here's where it all gets confusing (Keep in mind I'm not an advanced js programmer)
I have an array of html elements
let fields = document.getElementsByClassName("f-field")
Every single element in the returned array contains a bunch of other html elements, it looks something like this.
<div class="f-field">
<textarea id="9008" name="Logo"></textarea>
</div>
The inner HTML can be textareas, selects, inputs, whatever...
I tried this and it says
"fields.filter is not a function"
fields.filter(field => field.getElementsByName("Logo"))
I'm assuming that filter does not work for an Array of html elements. Or am I doing this wrong?
Thanks in advance, I'm trying to really understand javascript
DOM query methods like getElementsByClassName and querySelector return collections that are array-like, but not actually arrays (HTMLCollection, NodeList). They have numbered keys you can iterate over, and length properties too, but do not support array generics like filter, forEach or map.
You can cast an array-like object into an array using array = Array.from(source). If you're writing ES6, you could also use the spread operator: array = [...source]
So, you could write your code as follows:
let fields = document.querySelectorAll('.f-field');
logos = Array.from(fields).filter(field => field.getElementsByName('logo'));
Then again, why do all that filtering and traversing when you could just pass a CSS selector straight to querySelectorAll? e.g.
let logos = Array.from(document.querySelectorAll('.f-field [name="logo"]'));
Yup this is a little tricky. getElementsByClassName does NOT return an Array. It returns an HTMLCollection, which behaves like an array in some ways (you can iterate over it and it has a length), but does not contain most of the Array methods.
You can convert to an array as follows
var filteredFields = [...document.getElementsByClassName("f-field")].filter(item => itemTest(item));
Find out more about the spread operator at MDN

ImmutableJS Set not flattening

I have the following code:
Immutable.Set(['valor1', 'valor2', 'valor2', 'valor3', ['valor4', 'valor5']]).flatten().toJS();
This doesn't work as expected, but returns the like it was inputted. If I treat it as a List, it works as expected:
Immutable.fromJS(['valor1', 'valor2', 'valor2', 'valor3', ['valor4', 'valor5']]).flatten().toJS(); // return flattened list
What's wrong with flatten function when using it with Set?
What's wrong with flatten function when using it with Set?
Nothing is wrong with it. It seems you have to wrong idea about how Set and flatten work. From the docs:
Flattens only others Iterable, not Arrays or Objects.
Immutable.fromJS(...) deeply converts the value to Maps and Lists, so the inner array is converted to an Immutable.List, and that's why it works. The constructor functions do not deeply convert, and so the set contains an array (which is not flattened).

Array.prototype.map() and Array.prototype.forEach()

I've an array (example array below) -
a = [{"name":"age","value":31},
{"name":"height (inches)","value":62},
{"name":"location","value":"Boston, MA"},
{"name":"gender","value":"male"}];
I want to iterate through this array of objects and produce a new Object (not specifically reduce).
I've these two approaches -
a = [{"name":"age","value":31},
{"name":"height (inches)","value":62},
{"name":"location","value":"Boston, MA"},
{"name":"gender","value":"male"}];
// using Array.prototype.map()
b = a.map(function(item){
var res = {};
res[item.name] = item.value;
return res;
});
console.log(JSON.stringify(b));
var newObj = [];
// using Array.prototype.forEach()
a.forEach(function(d){
var obj = {};
obj[d.name] = d.value;
newObj.push(obj)
});
console.log(JSON.stringify(newObj))
Is it not right to just use either one for this sort of operations?
Also, I'd like to understand the use case scenarios where one will be preferred over the other? Or should I just stick to for-loop?
As you've already discussed in the comments, there's no outright wrong answer here. Aside from some rather fine points of performance, this is a style question. The problem you are solving can be solved with a for loop, .forEach(), .reduce(), or .map().
I list them in that order deliberately, because each one of them could be re-implemented using anything earlier in the list. You can use .reduce() to duplicate .map(), for instance, but not the reverse.
In your particular case, unless micro-optimizations are vital to your domain, I'd make the decision on the basis of readability and code-maintenance. On that basis, .map() does specifically and precisely what you're after; someone reading your code will see it and know you're consuming an array to produce another array. You could accomplish that with .forEach() or .reduce(), but because those are capable of being used for more things, someone has to take that extra moment to understand what you ARE using them for. .map() is the call that's most expressive of your intent.
(Yes, that means in essence prioritizing efficiency-of-understanding over efficiency-of-execution. If the code isn't part of a performance bottleneck in a high-demand application, I think that's appropriate.)
You asked about scenarios where another might be preferred. In this case, .map() works because you're outputting an array, and your output array has the same length as your input array. (Again; that's what .map() does). If you wanted to output an array, but you might need to produce two (or zero) elements of output for a single element of input, .map() would be out and I'd probably use .reduce(). (Chaining .filter().map() would also be a possibility for the 'skip some input elements' case, and would be pretty legible)
If you wanted to split the contents of the input array into multiple output arrays, you could do that with .reduce() (by encapsulating all of them as properties of a single object), but .forEach() or the for loop would look more natural to me.
First, either of those will work and with your example there's no reason not to use which ever is more comfortable for your development cycle. I would probably use map since that is what is for; to create "a new array with the results of calling a provided function on every element in this array."
However, are you asking which is the absolute fastest? Then neither of those; the fastest by 2.5-3x will be a simple for-loop (see http://jsperf.com/loop-vs-map-vs-foreach for a simple comparison):
var newObj = [];
for (var i = 0, item; item = a[i]; i++) {
var obj = {};
obj[item.name] = item.value;
newObj.push(obj);
});
console.log(JSON.stringify(newObj));

Categories

Resources