Related
I have a function which groups anagrams together
function groupAnagrams(strs) {
let result = {};
for (let word of strs) {
let cleansed = word.split("").sort().join("");
if (result[cleansed]) {
result[cleansed].push(word);
} else {
result[cleansed] = [word];
}
}
console.log(Object.values(result));
return Object.values(result);
}
it prints the results in the following format
[ [ 'abc', 'bac', 'cba' ], [ 'fun', 'fun', 'unf' ], [ 'hello' ] ]
However I would like the output to look like the following
abc, bac, cba
fun, fun, unf
hello
How can I achieve this?
you can do something like this
const data = [ [ 'abc', 'bac', 'cba' ], [ 'fun', 'fun', 'unf' ], [ 'hello' ] ]
data.forEach(row => console.log(row.join(', ')))
//or
console.log(data.map(row => row.join(', ')).join('\n'))
Since it's a node.js-tagged question I'll give an example with os.EOL
const { EOL } = require('os');
const lines = [ [ 'abc', 'bac', 'cba' ], [ 'fun', 'fun', 'unf' ], [ 'hello' ] ];
const output = lines.map((words) => words.join(', ')).join(EOL);
process.stdout.write(output);
Here's another solutions...
function groupAnagram(arr){
let res = '';
arr.map(function(item){
res += `${item.join(', ')} \n\n`
})
console.log(res)
}
groupAnagram([ [ 'abc', 'bac', 'cba' ], [ 'fun', 'fun', 'unf' ], [ 'hello' ] ]
);
I struggled with a problem for more than an hour, how can I turn this nested array
[
[
{
"name": "1",
}
],
[
{
"name": "a",
},
{
"name": "b",
}
]
]
into this:
[
{
name: '1',
},
{
id: 'a-b',
grouped: [
{
name: 'a',
},
{
name: 'b',
},
],
},
]
I don't mind using lodash. Not sure should I flatten it before anything else would make things easier.
You could use map() to form the id and grab the parts needed to reconstruct the new array.
const data = [
[{
"name": "1",
}],
[{
"name": "a",
},
{
"name": "b",
}
]
];
const result = [
...data[0],
{
id: data[1].map(r => r.name).join("-"),
grouped: data[1]
}
];
console.log(result);
to flatten the array is a good start. That will remove the superfluous dimension from the rawArray:
const newArray = array.flat()
Now you have an array with three simple objects. The first will remain unchanged. The second element of your finalArray needs to be an object, so let's create it:
const obj = {}
the obj has two keys: id and grouped. The property of id is a string that we can create like this:
obj.id = newArray[1].name + "-" + newArray[2].name
the property of grouped remains the same:
obj.grouped = array[1]
so the finalArray is now straight forward:
const finalArray = [ newArray[0], obj ]
Put it all together in a function:
const rawArray1 = [
[
{
"name": "1a",
}
],
[
{
"name": "a",
},
{
"name": "b",
}
]
]
const rawArray2 = [
[
{
"name": "1b",
}
],
[
{
"name": "aa",
},
{
"name": "bb",
}
]
]
transformArray( rawArray1 )
transformArray( rawArray2 )
function transformArray( array ){
const newArray = array.flat()
const obj = {}
obj.id = newArray[1].name + "-" + newArray[2].name
obj.grouped = array[1]
const finalArray = [ newArray[0], obj ]
console.log(finalArray)
return finalArray
}
I managed to solve it using simple forEach, push, and flat. It's more simple than I thought, I was confused and stuck with map and reduce.
let result = [];
[
[{
"name": "1",
}],
[{
"name": "a",
},
{
"name": "b",
}
]
].forEach((val) => {
const [{
name
}] = val
if (val.length === 1) {
result.push({
name,
})
} else if (val.length > 1) {
result.push({
id: val.map(val2 => val2.name).join('-'),
grouped: val
})
}
})
console.log(result.flat())
const array1 = [
[{ name: "1" }],
[
{ name: "a" },
{ name: "b" }
]
]
const array2 = [
[{ name: "2" }],
[
{ name: "aa" },
{ name: "bb" },
{ name: "cc" }
]
]
transformArray( array1 )
transformArray( array2 )
function transformArray( array ){
const result = []
// destructure first array element for the first object:
const [ nameObj ] = array[0]
result.push( nameObj )
// map each object of the second array element into an
// an array of names, and then join the names together:
const dataObj = {}
dataObj.id = array[1].map(obj => obj.name).join('-')
dataObj.grouped = array[1]
result.push( dataObj )
console.log( result )
return result
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
example we have this js array (some kind like lat, lng):
items = [
[aa,aa],
[bb,bb],
[cc,cc]
]
the result that i expected should be like this:
A = [
[aa,aa],
[bb,bb]
]
B = [
[bb,bb],
[cc,cc]
]
You are trying to iterate over two consecutive elements (arrays), you can use ruby_cons.
Note: This is a Ruby solution to iterate over consecutive elements.
items.each_cons(2) do |arr|
p arr
end
in javascript, you can try sth like,
> items
[ [ 42.32, 47.32 ], [ 49.434, 41.343 ], [ 43.34, 43.45 ] ]
> container = []
[]
> for(var i = 0; i<items.length-1; i++) {
... container.push(items.slice(i, i+2));
... }
2
> container[0]
[ [ 42.32, 47.32 ], [ 49.434, 41.343 ] ]
> container[1]
[ [ 49.434, 41.343 ], [ 43.34, 43.45 ] ]
more generalized solution, inspired from ruby's each_cons(n) enumerable method.
> each_cons = function(enm, cons_size) {
... var results = [];
... /*
... * checking numericality like typeof cons_size == 'number'
... * might be useful. but i'am skipping it.
... */
... cons_size = (cons_size < 1 ? 1 : cons_size );
... // setting default to 2 might be more reasonable
... for (var i=0; i<=enm.length - cons_size; i++) {
..... results.push(enm.slice(i, i+cons_size));
..... }
... return results;
... }
[Function: each_cons]
> x = [1,2,3,4,5,6,7,8,9,0];
[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 ]
> each_cons(x, 0)
[ [ 1 ], [ 2 ], [ 3 ], [ 4 ], [ 5 ], [ 6 ], [ 7 ], [ 8 ], [ 9 ], [ 0 ] ]
> each_cons(x, 1)
[ [ 1 ], [ 2 ], [ 3 ], [ 4 ], [ 5 ], [ 6 ], [ 7 ], [ 8 ], [ 9 ], [ 0 ] ]
> each_cons(x, 2)
[ [ 1, 2 ],
[ 2, 3 ],
[ 3, 4 ],
[ 4, 5 ],
[ 5, 6 ],
[ 6, 7 ],
[ 7, 8 ],
[ 8, 9 ],
[ 9, 0 ] ]
> each_cons(x, 3)
[ [ 1, 2, 3 ],
[ 2, 3, 4 ],
[ 3, 4, 5 ],
[ 4, 5, 6 ],
[ 5, 6, 7 ],
[ 6, 7, 8 ],
[ 7, 8, 9 ],
[ 8, 9, 0 ] ]
>
> x= "hippopotomonstrosesquipedaliophobia"; //https://en.wiktionary.org/wiki/hippopotomonstrosesquipedaliophobia
'hippopotomonstrosesquipedaliophobia'
> each_cons(x, 3)
[ 'hip',
'ipp',
'ppo',
'pop',
'opo',
'pot',
'oto',
'tom',
'omo',
'mon',
'ons',
'nst',
'str',
'tro',
'ros',
'ose',
'ses',
'esq',
'squ',
'qui',
'uip',
'ipe',
'ped',
'eda',
'dal',
'ali',
'lio',
'iop',
'oph',
'pho',
'hob',
'obi',
'bia' ]
>
> x = [[1,2], ['a', 'b'], [2,3,4, {a: 5}]]
[ [ 1, 2 ], [ 'a', 'b' ], [ 2, 3, 4, { a: 5 } ] ]
> each_cons(x, 2)
[ [ [ 1, 2 ], [ 'a', 'b' ] ],
[ [ 'a', 'b' ], [ 2, 3, 4, [Object] ] ] ]
I have this input array already sorted on the key:
var sortedArray = [ [ 'de', [ 1 ] ],
[ 'elle', [ 1 ] ],
[ 'elle', [ 1 ] ],
[ 'la', [ 1 ] ],
[ 'la', [ 1 ] ],
[ 'la', [ 1 ] ],
[ 'le', [ 1 ] ],
[ 'maison', [ 1 ] ],
[ 'voiture', [ 1 ] ],
[ 'voiture', [ 1 ] ]
];
I want to obtain this reduced Array :
[ [ 'de', [ 1 ] ],
[ 'elle', [ 1, 1 ] ],
[ 'la', [ 1, 1, 1 ] ],
[ 'le', [ 1 ] ],
[ 'maison', [ 1 ] ],
[ 'voiture', [ 1, 1 ] ]
];
I proceed like that :
sortedArray.forEach((elem, index, arr) => {
if (elem[0] === arr[index + 1][0]){
arr[index][1].push(1);
arr.splice(index + 1, 1);
}
});
console.log(sortedArray);
But I can't understand why I obtain this result:
[ [ 'de', [ 1 ] ],
[ 'elle', [ 1, 1 ] ],
[ 'la', [ 1, 1 ] ],
[ 'la', [ 1 ] ],
[ 'le', [ 1 ] ],
[ 'maison', [ 1 ] ],
[ 'voiture', [ 1, 1 ] ]
]
Help would be apreciated.
The issue is that you're splicing your array while iterating over it without resetting your current index. One way to get the desired result while using splice is to do something like this:
sortedArray.forEach((elem, index, arr) => {
while (arr[index + 1] && elem[0] === arr[index + 1][0]){
arr[index][1].push(1);
arr.splice(index + 1, 1);
}
});
Basically we're changing the if statement to a while loop and adding an extra check.
Use Array.prototype.reduce to create a new array. Because the original array is sorted, you only need to push 1 to the last item in the array, as long as it's the same as the current item, and add a new item whenever that's not true:
var sortedArray = [
['de', [1]],
['elle', [1]],
['elle', [1]],
['la', [1]],
['la', [1]],
['la', [1]],
['le', [1]],
['maison', [1]],
['voiture', [1]],
['voiture', [1]]
];
var result = sortedArray.reduce(function(result, item) {
if (!result.length || item[0] !== result[result.length - 1][0]) { // check if 1st results array is empty or if current item 'key' doesn't match the last item it result
result.push([item[0], []]); // push a new 'key' item with an empty array of 1s
}
result[result.length - 1][1].push(1); // push 1 to last item in result
return result;
}, []);
console.log(result);
I am trying to write a function to flatten an array. I have part of the function working and I need help in the other half.
flatten: function(anyArray, singleLevel) {
if (singleLevel == true) {
flatArray = Array.prototype.concat.apply([], anyArray);
return flatArray;
}
flatArray = Array.prototype.concat.apply([], anyArray);
if (flatArray.length != anyArray.length) {
flatArray = someObject.array.flatten(flatArray);
}
return flatArray;
}
if I type
.flatten([[[1],[1,2,3,[4,5],4],[2,3]]], true);
I want it to flatten only one level:
[[1],[1,2,3,[4,5],4],[2,3]]
Modern JavaScript allows us to handle this very easily using a variety of techniques
Using Array.prototype.flat -
const arr =
[ [ 1 ], [ 2, 3, [ 4, 5, [ 6 ] ] ], [ 7, [ 8, 9 ] ] ]
const flatArr =
arr.flat(1) // 1 is default depth
console.log(JSON.stringify(arr))
console.log(JSON.stringify(flatArr))
// [[1],[2,3,[4,5,[6]]],[7,[8,9]]]
// [1,2,3,[4,5,[6]],7,[8,9]]
Using Array.prototype.flatMap -
const arr =
[ [ 1 ], [ 2, 3, [ 4, 5, [ 6 ] ] ], [ 7, [ 8, 9 ] ] ]
const flatArr =
arr.flatMap(x => x)
console.log(JSON.stringify(arr))
console.log(JSON.stringify(flatArr))
// [[1],[2,3,[4,5,[6]]],[7,[8,9]]]
// [1,2,3,[4,5,[6]],7,[8,9]]
Using a spread argument to Array.prototype.concat
const arr =
[ [ 1 ], [ 2, 3, [ 4, 5, [ 6 ] ] ], [ 7, [ 8, 9 ] ] ]
const flatArr =
[].concat(...arr)
console.log(JSON.stringify(arr))
console.log(JSON.stringify(flatArr))
// [[1],[2,3,[4,5,[6]]],[7,[8,9]]]
// [1,2,3,[4,5,[6]],7,[8,9]]
Older version of JavaScript (ECMAScript 5 and below) can use techniques like Function.prototype.apply -
var arr =
[ [ 1 ], [ 2, 3, [ 4, 5, [ 6 ] ] ], [ 7, [ 8, 9 ] ] ]
var flatArr =
Array.prototype.concat.apply([], arr)
console.log(JSON.stringify(arr))
console.log(JSON.stringify(flatArr))
// [[1],[2,3,[4,5,[6]]],[7,[8,9]]]
// [1,2,3,[4,5,[6]],7,[8,9]]
Using Array.prototype.reduce -
var arr =
[ [ 1 ], [ 2, 3, [ 4, 5, [ 6 ] ] ], [ 7, [ 8, 9 ] ] ]
var flatArr =
arr.reduce((r, a) => r.concat(a), [])
console.log(JSON.stringify(arr))
console.log(JSON.stringify(flatArr))
// [[1],[2,3,[4,5,[6]]],[7,[8,9]]]
// [1,2,3,[4,5,[6]],7,[8,9]]
Using a primitive for loop -
var arr =
[ [ 1 ], [ 2, 3, [ 4, 5, [ 6 ] ] ], [ 7, [ 8, 9 ] ] ]
var flatArr =
[]
for (var i = 0; i < arr.length; i = i + 1)
flatArr = flatArr.concat(arr[i])
console.log(JSON.stringify(arr))
console.log(JSON.stringify(flatArr))
// [[1],[2,3,[4,5,[6]]],[7,[8,9]]]
// [1,2,3,[4,5,[6]],7,[8,9]]
The concat array method expects one or more arrays as arguments, whose elements will be appended:
[1].concat([2, 3], [4]) // [1, 2, 3, 4]
So if you are using apply, that will flatten another level:
[].concat.apply([1], [[2], [3]]) // === [1].concat([2], [3])
So you can either use push instead of concat, or call (or just direct invocation) instead of apply to get only a single flattening level.
if you use ES6/ES2015 you can use spread operator. Something like this
console.log(...[[[1],[1,2,3,[4,5],4],[2,3]]])