how to convert multidimention array to arr in object - javascript

can you explain the logic how to convert this 2d array to array and in array has objects, here is the input :
const arr = [
["Tony", "a", "b"],
["Sara", "c", "z"]
];
how to convert them to be:
obj = [
{
name:"Tony",
first:"a",
second:"b"
},
{
name:"Sara",
first:"c",
second:"z"
}
]
should we create 2 objects temporary and are ? to put them in the array,
and how about looping? can we just use one-time looping?
and how if that 2d array length is not same with ther 2d on the first or the second,
i do love to know the method, with explaning if you dont mind,
and i do like you all dont use ES6 for this :), so i know the logic

Use Array.map(). In the map's callback, extract the values to variables, using array destructuring, than create the object with shorthand property names:
const arr = [["Tony", "a", "b"], ["Sara", "c", "z"]];
const result = arr.map(([name, first, second]) => ({
name,
first,
second
}));
console.log(result);
And if you don't want to use Array.map(), you can build one using a for...of loop:
const map = (arr, cb) => {
const r = [];
for(const item of arr) {
r.push(cb(item));
}
return r;
};
const arr = [["Tony", "a", "b"], ["Sara", "c", "z"]];
const result = map(arr, ([name, first, second]) => ({
name,
first,
second
}));
console.log(result);

You can use .map() with some array destructuring:
const arr = [
["Tony", "a", "b"],
["Sara", "c", "z"]
];
const result = arr.map(([name, first, second]) => ({name, first, second}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Alternatively, you can use a simple for loop:
const arr = [
["Tony", "a", "b"],
["Sara", "c", "z"]
];
const result = [];
for(var i = 0; i < arr.length; i++) {
result.push({
name: arr[i][0],
first: arr[i][1],
second: arr[i][2]
});
}
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

var arr = [["Tony", "a", "b"], ["Sara", "c", "z"]];
function parseData(input){
var output = [];
for(var i = 0; i< input.length ; i++){
output.push({name:input[i][0],first:input[i][1],second:input[i][2]})
}
return output;
}
console.log(parseData(arr));
EDIT - Explanation
As the input is structured as 2D array with inner array is of fixed length of 3 and outer is of non-negative ( >= 0 ). Iterate over the outer array using for loop and inner array using the index number and store the result in output array.
JsFiddle demo - https://jsfiddle.net/53umf8rv/

Without Map:
const arr = [
["Tony", "a", "b"],
["Sara", "c", "z"]
];
obj=[];
for(innerArr of arr)
{
obj.push({"name":innerArr[0],"first":innerArr[1],"second":innerArr[2]});
}
console.log(obj);

Without using higher order functions you can achieve this using a for of loop:
const arr = [
["Tony", "a", "b"],
["Sara", "c", "z"]
];
let obj_arr = [];
for(inner_arr of arr) {
obj_arr = [...obj_arr, {name: inner_arr[0], first: inner_arr[1], second: inner_arr[2]}];
}
console.log(obj_arr);

You could use an outer for ... of statement, which iterates the items of the array and iterate the inner array by using a classic for statement with an index variable, which is used to get the corresponding key value as well.
For each inner iteration take a new property for the temporary object and assign a value. At the end of the inner iteration push the temporary object to the result set.
function convert(array, keys) {
var result = [],
items,
i,
temp;
for (items of array) {
temp = {};
for (i = 0; i < items.length; i++) {
temp[keys[i]] = items[i];
}
result.push(temp);
}
return result;
}
console.log(convert([["Tony", "a", "b"], ["Sara", "c", "z"]], ["name", "first", "second"]));

Related

Get only values from a map (which has values as array) to an array typescript

I want to get values of a map (which has values as array) and store inside a string array in typescript.
myMap = {0:['a','b','c'], 1:['d','e'], 2:['f','g']};
Expected Result arr['a','b','c','d','e','f','g']
Updated: I haven't used flat() function before. Without flat() function it gives below result.
myMap = { 0: ["a", "b", "c"], 1: ["d", "e"], 2: ["f", "g"] };
const result = Object.values(myMap);
console.log(result);
Get all values of object using Object.values and then flat the array.
myMap = { 0: ["a", "b", "c"], 1: ["d", "e"], 2: ["f", "g"] };
const result = Object.values(myMap).flat();
console.log(result);
get the key and valueArray. the iterate through the valueArray.
const myMap = {0:['a','b','c'], 1:['d','e'], 2:['f','g']};
var arr = [];
for (const [key, valueArr] of Object.entries(myMap)) {
for (var i = 0; i < valueArr.length; i++) {
arr.push(valueArr[i]);
}
}
console.log(arr);

How do I filter array of objects based on a list of possible ID properties?

I'm trying to filter arr2. If the element doesn't have an ID listed in arr, then I want it to be removed. How could I make this happen in javascript?
var arr= ["a", "b", "d"]
var arr2=[{id:"a", value:1},{id:"b", value:2}, {id:"c", value:3}]
result:
[{id:"a", value:1},{id:"b", value:2}]
Thanks in advance :)
You can use reduce and in the callback function check if arr includes the id of the object under iteration. If so then add the elements in the accumulator array
var arr = ["a", "b", "d"]
var arr2 = [{
id: "a",
value: 1
}, {
id: "b",
value: 2
}, {
id: "c",
value: 3
}];
const newData = arr2.reduce((acc, curr) => {
if (arr.includes(curr.id)) {
acc.push(curr)
}
return acc;
}, []);
console.log(newData)
if arr items are always strings you can do this:
var arr = ["a", "b", "d"];
var arr2 = [{id:"a", value:1},{id:"b", value:2}, {id:"c", value:3}];
let str = arr.join('')
let filtered = arr2.filter(x => str.includes(x.id));
console.log(filtered)
this should do it
var arr= ["a", "b", "d"]
var arr2=[{id:"a", value:1},{id:"b", value:2}, {id:"c", value:3}]
const filteredArray = arr2.filter(obj => {
return arr.includes(obj.id)
})
Using filter, reduce, and includes are all nearly twice as slow as simply using a loop. To walk you through it, all it does is check over every element in the second array and check to see if it's id property is in the first array, and if it is, it clones it. Also, for future reference, that title is written poorly. A much better title would be "How to filter array of objects based on a list of possible ID properties"
var arr= ["a", "b", "d"]
var arr2=[{id:"a", value:1},{id:"b", value:2}, {id:"c", value:3}]
let clone = []
for(let i = 0;i < arr2.length;i++){
for(let j = 0;j < arr.length; j++) if(arr2[i].id === arr[j]) clone.push(arr2[j])
}
console.log(clone)

Search array, find elements with ids specified another array, extract a property from the results

I have two arrays,
array1 = [{name: "a", id: 1},{name: "b", id: 2},{name: "c", id: 3}]
and
array2 = [1, 2] // --which are the ids
I want to return a new array (array3) to display ["a", "b"] and if array2 = [1,3] then array3 should be ["a", "c"]
In other words, I would like to create a new array, with the names, corresponding to its id.
You can use reduce:
let a1 = [{name:'a', id:1},{name:'b', id:2},{name:'c', id:3}]
let a2 = [1,3]
let a3 = a1.reduce((carry, current) => {
if (a2.includes(current.id)) {
carry.push(current.name)
}
return carry
}, [])
alert(a3)
User filter to select the elements that meet your criteria, and map to get the property you want.
const array1 = [{name:"a", id:1},{name:"b", id:2},{name:"c", id:3}];
const array2=[1,2];
const array3 = array1.filter(i => array2.includes(i.id)).map(i => i.name);
array3 will contain ["a", "b"]
I would go ahead and perform the below:
for(int i = 0; i<array1.length(); ++i){
for(int j = 0; j<array2.length(); ++j){
if (array1[i].id==array2[j]){
array3[j] = array[i].name;
}
}
}
Hope this is simple and it helps!

Create Dynamically Nested Objects with loops

I wanna create a nested object dynamically. I can create it hard coded. Is it possible to do this with a loop ?
result = {}
keys = ["a", "b", "c", "d"]
result[keys[0]] = {}
result[keys[0]][keys[1]] = {}
result[keys[0]][keys[1]][keys[2]] = {}
result[keys[0]][keys[1]][keys[2]][keys[3]] = "cool"
I want to pass an integer for example if it is "3", this should created an object like:
result = {
"a": {
"b": {
"c": "cool"
}
}
}
If it is 4, :
result = {
"a": {
"b": {
"c": {
"d": "cool"
}
}
}
}
So on ...
edit:
I am also checking result object, in order to create this nested structure. If there is not any field yet, I simply create the object.
Using this structure to group data.
Any chance to check these dynamically ?
if (!result[keys[0]])
if (!result[keys[0]][keys[1]])
if (!result[keys[0]][keys[1]][keys[2]])
You can use reduceRight() for this. It just starts from the inside at the last item in the keys list and works its way out starting with "cool":
let keys = ["a", "b", "c", "d"]
let limit = 3
let result = keys.reduceRight((obj, key) => ({[key]: obj}), "cool")
console.log(result)
To limit where the object stops you can iterate over a slice of the keys. For example:
let keys = ["a", "b", "c", "d"]
let start = 0
let stop = 3 // slices are don't inlcude the last item, so this will stop at index 2
let result = keys.slice(start, stop).reduceRight((obj, key) => ({
[key]: obj
}), "cool")
console.log(result)
simple for-loop solution.
let result = {}
let keys = ["a", "b", "c", "d"]
let depth=3;
let current = result
for(let i=0;i<depth;++i){
let key = keys[i]
if(i == depth-1) current[key] = 'cool'
else current = current[key] = {}
}
console.log(result)
If you like to add to a given object a new property, you could reduce the keys with the object and take default objects for not given keys. At the end assign the value.
function setValue(object, path, value, limit) {
var keys = path.slice(0, limit),
last = keys.pop();
keys.reduce((o, k) => o[k] = o[k] || {}, object)[last] = value;
return object;
}
var result = { foo: 42 },
keys = ["a", "b", "c", "d"];
setValue(result, keys, 'cool');
console.log(result);
setValue(result, keys, 'cool', 3);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
short and simple using reduce
let object1= {}
keys = ['a', 'b', 'c']
keys.reduce((prev,curr,i)=>{
prev[curr] = {}
return prev[curr]
}, object1)
log(object1)
// {
// a:{
// b:{
// c:{}
// }
// }
// }
I'd use a reducer, along with some basic tests to help me out:
https://youtu.be/D6zLI8zrfVs
https://gist.github.com/brianswisher/2ce1ffe3ec08634f78aacd1b7baa31f9

split an array into two based on a index in javascript

I have an array with a list of objects. I want to split this array at one particular index, say 4 (this in real is a variable). I want to store the second part of the split array into another array. Might be simple, but I am unable to think of a nice way to do this.
Use slice, as such:
var ar = [1,2,3,4,5,6];
var p1 = ar.slice(0,4);
var p2 = ar.slice(4);
You can use Array#splice to chop all elements after a specified index off the end of the array and return them:
x = ["a", "b", "c", "d", "e", "f", "g"];
y = x.splice(3);
console.log(x); // ["a", "b", "c"]
console.log(y); // ["d", "e", "f", "g"]
use slice:
var bigOne = [0,1,2,3,4,5,6];
var splittedOne = bigOne.slice(3 /*your Index*/);
I would recommend to use slice() like below
ar.slice(startIndex,length);
or
ar.slice(startIndex);
var ar = ["a","b","c","d","e","f","g"];
var p1 = ar.slice(0,3);
var p2 = ar.slice(3);
console.log(p1);
console.log(p2);
const splitAt = (i, arr) => {
const clonedArray = [...arr];
return [clonedArray.splice(0, i), clonedArray];
}
const [left, right] = splitAt(1, [1,2,3,4])
console.log(left) // [1]
console.log(right) // [2,3,4]
const [left1, right1] = splitAt(-1, [1,2,3,4])
console.log(left1) // []
console.log(right1) // [1,2,3,4]
const [left2, right2] = splitAt(5, [1,2,3,4])
console.log(left1) // [1,2,3,4]
console.log(right1) // []
Some benefits compared to other solutions:
You can get the result with a one liner
When split index is underflow or overflow, the result is still correct. slice will not behave correctly.
It does not mutate the original array. Some splice based solutions did.
There is only 1 splice operation, rather than 2 slice operations. But you need to benchmark to see if there is actual performance difference.
You can also use underscore/lodash wrapper:
var ar = [1,2,3,4,5,6];
var p1 = _.first(ar, 4);
var p2 = _.rest(ar, 4);
Simple one function from lodash:
const mainArr = [1,2,3,4,5,6,7]
const [arr1, arr2] = _.chunk(mainArr, _.round(mainArr.length / 2));
const splitArrayByIndex = (arr, index) => {
if (index > 0 && index < arr.length) {
return [arr.slice(0, index), arr.slice(-1 * (arr.length - index))]
}
}
const input = ['a', 'x', 'c', 'r']
const output = splitArrayByIndex(input, 2)
console.log({ input, output })

Categories

Resources