Concat two arrays retuning circular js - javascript

I have an array (JSON objects):
result = [[{object},{object}], [{object}], [{object},{object},{object}]]
And I am trying to get it into a single array of objects:
array = [{object},{object},{object}],{object},{object},{object}]
However no matter which method I try I something like is output from console.log(array):
[{object}, [circular], {object}, [circular], [circular] etc
I have no idea what circular like this is?
var array = [];
for (var i=0; i<result.length;i++) {
array = array.concat(result[i]);
}
or:
for (var i=0; i<result.length;i++) {
var res = result[i];
for (var x=0; x<res.length; x++){
array.push(res[x]);
}
}

You probably need some recursive function which is pushing elements in an accumulator.
When it's not an array, simply push it, otherwise, push its components:
var isArray = function(someVar) {
return Object.prototype.toString.call( someVar ) === '[object Array]';
};
var flattenArrayAux = function(arr, accum) {
for(var i = 0; i < arr.length; ++i) {
if(isArray(arr[i])) {
flattenArrayAux(arr[i], accum);
}
else {
accum.push(arr[i]);
}
}
}
var flattenArray = function(arr) {
var result = [];
flattenArrayAux(arr, result);
return result;
}
document.write(flattenArray([[1, 2, 3], 4, [[5, 6], [7, 8]]]))

If the initial array contains only 2 levels as your example (no elements inside arrays are arrays), this would work:
var array = result.reduce(function(a,b){
return a.concat(b);
});
using reduce and concat does the trick, returning all elements in a single array.

If I properly understand your question, you need something like this:
var arrays = [[{a:1},{b: 2}], [{c:3}], [{d: 4},{e: 5},{f: 6}]];
function flattenArray(arr, result) {
var res = result || [];
arr.forEach(function(item){
if (Array.isArray(item)) {
flattenArray(item, res)
} else {
res.push(item)
}
})
return res;
}
console.log(flattenArray(arrays))

Using lodash flattenDepth
array = [ [object,object], [object], [object,object,object] ]
_.flattenDepth(array, 1);
Demo

Related

Making subarrays from an array algorithm javascript [duplicate]

I have a JavaScript array with 8 elements and some elements are repeating. I want to create separate arrays for identical elements.
example:
original array is [1,1,1,3,3,1,2,2]
resulting arrays will be [1,1,1,1],[3,3],[2,2]
I want a function similar to this:
var array=[1,1,1,3,3,1,2,2];
var createNewArrays=function(array){
for (var i = 0; i < array.length; i++) {
for (var j = 0; j < array.length; j++) {
}
}
};
You could use a hash table as reference to the sub arrays for the collection.
var array = [1, 1, 1, 3, 3, 1, 2, 2],
result = [];
array.forEach(function (a) {
a in this || result.push(this[a] = []);
this[a].push(a);
}, Object.create(null));
console.log(result);
var arr = [1,1,1,3,3,1,2,2];
var hash = Object.create(null);
var result = arr.reduce(function(r, n) {
if(!hash[n]) {
hash[n] = [];
r.push(hash[n]);
}
hash[n].push(n);
return r;
}, []);
console.log(result);
And an ES6 solution that uses Map, and spread:
const arr = [1,1,1,3,3,1,2,2];
const result = [...arr.reduce((r, n) =>
r.set(n, (r.get(n) || []).concat(n)),
new Map()).values()];
console.log(result);
Let's assume you want the resulting arrays to be properties on an object keyed by the value they represent. You just loop through the array, creating or adding to the arrays on the object properties as you go:
var array=[1,1,1,3,3,1,2,2];
var result = {};
array.forEach(function(entry) {
(result[entry] = result[entry] || []).push(entry);
});
console.log(result);
That's a bit dense, here's a clearer version:
var array=[1,1,1,3,3,1,2,2];
var result = {};
array.forEach(function(entry) {
var subarray = result[entry];
if (!subarray) {
subarray = result[entry] = [];
}
subarray.push(entry);
});
console.log(result);

Difference between normal for loop and for...in?

I'm trying to write a function to fulfil the following requirements:
Given an object and a key, "getElementsThatEqual10AtProperty" returns an array containing all the elements of the array located at the given key that are equal to ten.
Notes:
If the array is empty, it should return an empty array.
If the array contains no elements are equal to 10, it should return
an empty array.
If the property at the given key is not an array, it should return an
empty array.
If there is no property at the key, it should return an empty array.
Example:
var obj = {
key: [1000, 10, 50, 10]
};
var output = getElementsThatEqual10AtProperty(obj, 'key');
console.log(output); // --> [10, 10]
Approach #1 (fails the final point *If there is no property at the key, it should return an empty array.):
function getElementsThatEqual10AtProperty(obj, key) {
var output = [];
for (var i = 0; i < obj[key].length; i++) {
if (obj[key][i] === 10) {
output.push(obj[key][i]);
}
}
return output;
}
Approach #2 passes all:
function getElementsThatEqual10AtProperty(obj, key) {
var output = [];
for (let i in obj[key]) {
if (obj[key][i] === 10) {
output.push(obj[key][i]);
}
}
return output;
}
From my understanding, both loops and the subsequent conditional push has the same logic. Why does one work over the other?
You're making this more complicated than it needs to be. I would just do this:
function getSameVals(yourArray, val){
var a = [];
for(var i=0,l=yourArray.length; i<l; i++){
if(yourArray[i] === val){
a.push(val);
}
}
return a;
}
var ten = getSameVals(obj.key, 10);
console.log(ten);

Modify an object to a new Array in Javascript

sorry, i m a beginner in javascript.
Can someone explain me how to modify this Object
{toto:[12,13,15],titi:[45,12,34]}
to this Array
newArray = [
{
toto:12,
titi:45
},{
toto:13,
titi:12
},{
toto:15,
titi:34}
]
Also, what the solution if the toto and titi doesn't have the same lenght
Thanks for support!
Here's how I did it. In this way, you don't need to know the names of the keys or the size of the array, but it does require a few loops.
obj = {toto:[12,13,15],titi:[45,12,34]};
newArray = [];
// Find the longest array in your data set
longest = 0;
Object.keys(obj).forEach(function(key) {
if (obj[key].length > longest) {
longest = obj[key].length;
}
});
// Loop through the existing data set to create new objects
for (i = 0; i<longest; i++) {
newObject = {};
Object.keys(obj).forEach(function(key) {
newObject[key] = obj[key][i];
});
newArray.push(newObject);
}
console.log(newArray);
plnkr.co demo in the script.js file.
If you want to ignore keys that would have undefined values for uneven loops, you can add a conditional inside the forEach loop that creates a new object:
Object.keys(obj).forEach(function(key) {
if (obj[key][i] !== undefined) {
newObject[key] = obj[key][i];
}
});
Assuming lengths of toto and titi are the same:
Obj = {toto:[12,13,15],titi:[45,12,34]};
newArray = [];
for (var k in Obj["toto"]) {
newArray.push({ toto:Obj["toto"][k],titi:Obj["titi"][k] });
}
Since the lengths of your inner arrays are equal, you should be able to simply loop through them and add a value from each array (for each iteration) into a new array :
// Your input
var input = {toto:[12,13,15],titi:[45,12,34]};
// An array to store your output
var output = [];
// Since your inner arrays are of equal size, you can loop through them
// as follows
for(var i = 0; i < input.toto.length; i++){
output.push({ toto: input.toto[i], titi: input.titi[i]});
}
You can see a working example of this here and what the output array looks like below :
A more generic approach
var object = { toto: [12, 13, 15], titi: [45, 12, 34] },
newArray = function (o) {
var keys = Object.keys(o),
l = keys.reduce(function (r, a) { return Math.max(r, o[a].length); }, 0),
i = 0,
t,
result = [];
while (i < l) {
t = {};
keys.forEach(function (k) { t[k] = o[k][i]; });
result.push(t);
i++;
}
return result;
}(object);
document.write('<pre>' + JSON.stringify(newArray, 0, 4) + '</pre>');

Iterative solution for flattening n-th nested arrays in Javascript

Can anyone show me an iterative solution for the following problem? I solved it recursively but struggled with an iterative solution. (Facebook Technical Interview Question)
Input: [1, {a: 2}, [3], [[4, 5], 6], 7]
Output: [1, {a: 2}, 3, 4, 5, 6, 7]
Solution must work with n-th nested array elements (i.e. it must still work if someone modifies the array values/placement in the example above)
Recursive solution:
var flatten = function(input) {
var result = [];
input.forEach(function(element) {
result = result.concat(Array.isArray(element) ? flatten(element) : element);
});
return result;
}
Here is one way:
var input = [1, {a: 2}, [3], [[4, 5], 6], 7];
function flatten(input) {
var i, placeHolder = [input], lastIndex = [-1], out = [];
while (placeHolder.length) {
input = placeHolder.pop();
i = lastIndex.pop() + 1;
for (; i < input.length; ++i) {
if (Array.isArray(input[i])) {
placeHolder.push(input);
lastIndex.push(i);
input = input[i];
i = -1;
} else out.push(input[i]);
}
}
return out;
}
flatten(input);
Explanation: If iterating over a nested structure, you just have to remember where you were before by saving the current array and position before moving into the nested array (this is usually taken care of via the stack for recursive solutions).
Note: If you reuse the arrays placeHolder and lastIndex you won't need to keep recreating them every time. Perhaps something like this:
var flatten = function(){
var placeHolder = [], lastIndex = [];
placeHolder.count = 0;
lastIndex.count = 0;
return function flatten(input) {
var i, out = [];
placeHolder[0] = input; placeHolder.count = 1;
lastIndex[0] = -1; lastIndex.count = 1;
while (placeHolder.count) {
input = placeHolder[--placeHolder.count];
i = lastIndex[--lastIndex.count] + 1;
for (; i < input.length; ++i) {
if (Array.isArray(input[i])) {
placeHolder[placeHolder.count++] = input;
lastIndex[lastIndex.count++] = i;
input = input[i];
i = -1;
} else out.push(input[i]);
}
}
return out;
}
}();
This is even faster again (for flat iteration that is), and less garbage collector issues calling it many times. The speed is very close to that of recursive function calling in Chrome, and many times faster than recursion in FireFox and IE.
I recreated Tomalak's tests here since the old jsPerf is broken for editing: https://jsperf.com/iterative-array-flatten-2
How about this?
inp = [1, {a: 2}, [3], [[4, 5], 6], 7]
out = inp;
while(out.some(Array.isArray))
out = [].concat.apply([], out);
document.write(JSON.stringify(out));
Works, but not recommended:
var flatten = function(input) {
return eval("[" + JSON.stringify(input).
replace(/\[/g,"").replace(/\]/g,"") + "]");
}
Here's a solution that flattens in place.
function flatten(arr) {
var i = 0;
if (!Array.isArray(arr)) {
/* return non-array inputs immediately to avoid errors */
return arr;
}
while (i < arr.length) {
if (Array.isArray(arr[i])) {
arr.splice(i, 1, ...arr[i]);
} else {
i++;
}
}
return arr;
}
This solution iterates through the array, flattening each element one level of nesting at a time until it cannot be flattened any more.
function flatten(array){
for(var i=0;i<array.length;i++)
if(Array.isArray(array[i]))
array.splice.apply(array,[i,1].concat(array[i--]));
return array;
}
This in-place solution is faster than Lupe's, now that I've removed all of the inner curly brackets (I inlined the i-- in the concat parameter to do that).
A different iterative algorithm:
function flatten2(input) {
var output = [];
var todo = [input];
var current;
var head;
while(todo.length) {
var current = todo.shift();
if(Array.isArray(current)) {
current = current.slice();
head = current.shift();
if(current.length) {
todo.unshift(current)
}
todo.unshift(head);
} else {
output.push(current);
}
}
return output;
}
Put all elements on a stack.
While the stack is not empty, remove the first element.
If that element is a scalar, add it to the output.
If that element is an array, split it into head (first element) and tail (remaining elements) and add both to the stack.
As Tomalak's JSPerf shows, this is pretty slow.
JSBin
A fairly concise, readable algorithm:
function flatten(input) {
var output = [];
var todo = [input];
var current;
while(todo.length) {
var current = todo.shift();
if(Array.isArray(current)) {
todo.unshift.apply(todo, current)
} else {
output.push(current);
}
}
return output;
}
This version performs better than my other answer, but is still significantly slower than James Wilkins' answer.
JSBin
Tomalak's JSPerf
Here are two approaches, recursive and iterative and their comparison to Array.flat.
Maybe it'll help someone
const arrayToFlatten = [[1], [2, [3]], null, [[{}]], undefined];
// takes an array and flattens it recursively, default depth is 1 (just like Array.flat())
function flattenRecursive(arr, depth = 1) {
let myArray = [];
if (depth === 0){ // if you've reached the depth don't continue
myArray = arr;
} else if(!Array.isArray(arr)) { // add item to array if not an array
myArray.push(arr);
} else { // flatten each item in the array then concatenate
arr.forEach(item => {
const someNewArray = flattenRecursive(item, depth - 1);
myArray = myArray.concat(someNewArray);
});
}
return myArray;
}
// takes an array and flattens it using a loop, default depth is 1 (just like Array.flat())
function flattenIterative(arr, depth = 1) {
let result = arr;
// if an element is an array
while(result.some(Array.isArray) && depth) {
// flatten the array by one level by concating an empty array and result using apply
result = [].concat.apply([], result);
depth--; // track depth
}
return result;
}
console.log(arrayToFlatten.flat(2)); // ES^
console.log(flattenRecursive(arrayToFlatten, 2));
console.log(flattenIterative(arrayToFlatten, 2));
Here's my solution to this:
function flattenList(A) {
let result = []
for (let i=0; i < A.length; i++) {
if (typeof A[i] == "object"){
let item = reduceArray(A[i])
result.push(...item)
}else {
result.push(A[i])
}
}
return result
}
function reduceArray(arr){
while(arr.some(Array.isArray)) {
let item = arr.find(Array.isArray)
let index = arr.indexOf(item)
arr[index] = item[0]
}
return arr
}
Not sure if the "stack" approach was used properly in previous answers. I think it could be simpler, like this:
function flatten(arr) {
const result = [];
const stack = [arr];
while (stack.length) {
const curr = stack.pop();
if (Array.isArray(curr)) {
for (let i = curr.length - 1; i >= 0; i--) {
stack.push(curr[i]);
}
} else {
result.push(curr);
}
}
return result;
}
Not sure why the other answers are so complicated, this can easily be achieved by looping through the array and flattening each entry until it's no longer an array.
const flatten = (arr) => {
for (let i = 0; i < arr.length; i++) {
while (Array.isArray(arr[i])) {
arr.splice(i, 1, ...arr[i]);
}
}
return arr;
}

How to find array in array and remove it?

var arr = [["test","1"],["demo","2"]];
// $.inArray() ???
// .splice() ???
// $.each() ???
$("code").html(JSON.stringify(arr));
If I will find matching array by "test" (unique) keyword , I will remove ["test","1"]
So arr after removed will be [["demo","2"]]
How can I do that ?
Playground : http://jsbin.com/ojoxuy/1/edit
This is what filter is for:
newArr = arr.filter(function(item) { return item[0] != "test" })
if you want to modify an existing array instead of creating a new one, just assign it back:
arr = arr.filter(function(item) { return item[0] != "test" })
Modificator methods like splice make code harder to read and debug.
You could do something like this:
function remove(oldArray, itemName) {
var new_array = [];
for(var i = 0, len = oldArray.length; i < len; i++) {
var arr = oldArray[i];
if (arr[0] != itemName) new_array.push(arr);
}
return new_array;
}
And call it like this:
var arr = [["test","1"],["demo","2"]];
var new_arr = remove(arr,'test');
I'm making assumptions here and not doing any real error checking but you get the idea.
Perhaps something like:
for(var i = 0; i < arr.length; i++) {
if(arr[i][0] == "test") {
arr.splice(i, 1);
break;
}
}
var arr = [["test","1"],["demo","2"]];
function checkArrayElements(a, index, arr) {
if(a[0]=="test"){
delete arr[index];
arr.splice(index,index+1);
}
}
arr.forEach(checkArrayElements);
$("code").html(JSON.stringify(arr));
NOTE: This removes any inner array in arr with the 0 element = "test"
Check this one
function rmEl(a,v)
{
for(var i=0;i<a.length;i++)
{
if(a[i][0]==v)
{
a.splice(i,i+1);
i=-1;
}
$("code").html(JSON.stringify(a));
}
return a;
}

Categories

Resources