I have the array ["oop", "poo", "oop", "kkd", "ddd", "kkd"].
Is there any elegant way I can split it to sub-arrays, so each array contains elements with same values?
I want to achieve the following
var arrayOne = ["oop", "oop"]
var arrayTwo = ["poo"]
var arrayThree = ["kkd", "kkd"]
var arrayFour = ["ddd"]
You could use reduce.
var arr = ["oop", "poo", "oop", "kkd", "ddd", "kkd"];
var mapped = arr.reduce((map, val)=>{
if(!map[val]) {
map[val]=[];
}
map[val].push(val);
return map;
}, {});
You can even get weird and make it a 1 liner, although probably not the brightest idea just in terms of clarity.
arr.reduce((m, v)=>(m[v]=m[v]||[]).push(v) && m, {});
You could maybe do something like this, but the requirement kinda feels like a code smell in the first place.
const mixedArray = ["oop", "poo", "oop", "kkd", "ddd", "kkd"];
const splitArrays = {};
mixedArray.forEach(v => {
if (!!splitArrays[v]) {
splitArrays[v].push(v);
} else {
splitArrays[v] = [v];
}
})
console.log(splitArrays);
edit: If functional purity is a concern then ug_'s use of reduce is ipso facto preferable.
You can create a dictionary counting the values:
counter = {}
L = myArray.length
for (var i = 0; i < L; i++)
{
if (myArray[i] in counter)
{
counter[myArray[i]]+=1
}
else
{
counter[myArray[i]]=1
}
}
You could reduce and destructure
var arr = ["oop", "poo", "oop", "kkd", "ddd", "kkd"];
var obj = arr.reduce( (a,b) => (a[b] = a[b] + 1 || 1, a), {});
var [arrayOne, arrayTwo, arrayThree, arrayFour] = Object.keys(obj).map(k=>Array(obj[k]).fill(k));
console.log(arrayOne, arrayTwo, arrayThree, arrayFour);
Related
I was wanting to see if there is a relatively simple method for doing this as I can use the following:
var arr = [ "Client", "ActType", "CallRepType"];
var arr2 = [ "ECF", "Meeting", "Call Report"]
var myobj = arr2.map(value => ({'Client': arr2[0], 'ActType': arr2[1], 'CallRepType': arr2[2]}));
But I get the same correct object 3 times in a row...I simply want a single object returned that looks like:
{Client: 'ECF', ActType: 'Meeting', CallRepType: 'Call Report'}
I know I can loop through both arrays but I was hoping to get a solution using map, reduce or taking advantage of spread in javascript...
A faster solution that uses Array.prototype.forEach():
var arr = [ "Client", "ActType", "CallRepType"];
var arr2 = [ "ECF", "Meeting", "Call Report"]
var result = {};
arr.forEach((el, i) => { result[el] = arr2[i]; });
console.log(result);
Array.prototype.forEach()`
This a solution that uses Array.reduce() to create the object:
const arr = [ "Client", "ActType", "CallRepType"];
const arr2 = [ "ECF", "Meeting", "Call Report"]
const myobj = arr.reduce((r, key, i) => {
r[key] = arr2[i];
return r;
}, {});
console.log(myobj);
You can loop through the array and do it:
var arr = [ "Client", "ActType", "CallRepType"];
var arr2 = [ "ECF", "Meeting", "Call Report"];
var len = arr.length;
var myObj = {};
for (var i = 0; i < len; i++) {
var myObject = {};
myObj[arr[i]] = arr2[i]
// myObj.push = myObject;
}
console.log(myObj);
I have two array. I want to merge this two arrays into one array. One array consisting keys and another one values.My array looks like
productId = [8,7,9];//Key Element
quantity = ["5","1","3"];//Value Element
//expected new array
newarray = {
"8": 5,
"7": 1,
"9": 3
}
I already tried to merge these arrays, in this way
var newArray = {};
for(var i=0; i< productId.length; i++){
newArray[productId[i]] = quantity [i];
}
console.log(newArray);
It returns
Object [ <7 empty slots>, "5", "1", "3" ]
You are working in firefox so you may get this type of issue because the problem might be caused at how Firefox' console.log has interpreted the input object.
Please look here
Empty slots in JavaScript objects?
Try this
var productId = [8,7,9];
var quantity = ["5","1","3"];
var newarray = {};
productId.forEach((key, i) => newarray[key] = quantity[i]);
console.log(newarray);
Try the following:
var productId = [8,7,9];//Key Element
var quantity = ["5","1","3"];//Value Element
var obj = {};
var i = 0;
for(var k of productId) {
obj[k] = parseInt(quantity[i]);
i++;
}
console.log(obj);
Your new "array" is not an Array but an Object.
You can iterate on one of the arrays using Array.reduce to construct the object.
Something like that:
const arr1 = ['8', '2', '4'];
const arr2 = ['28', '12', '45'];
const result = arr1.reduce((obj, currentItem, index) => {
obj[currentItem] = arr2[index];
return obj;
}, {});
console.log(result);
I have below two arrays:
array1 = [{
"type":"test",
"name":"name1"},
{
"type":"dev",
"name":"name2"}]
array2=[{
"type":"test",
"name":"name3"},
{
"type":"dev",
"name":"name4"},
{
"type":"prod",
"name":"name5"}]
I want to group two arrays with "type" and create a new array something like this:
finalArray=[{
"type":"test",
"info":[{
"type":"test",
"name":"name1"}],
[{
"type":"test",
"name":"name3"
}]},
{
"type":"dev",
"info":[{
"type":"dev",
"name":"name2"}],
[{
"type":"dev",
"name":"name4"}]},
{
"type":"prod",
"info":[],
[{
"type":"prod",
"name":"name5"}]
}]
Is there anyway that I can achieve this using javascript, angularjs2, lodash, jquery. I am able to group and create new object as mentioned in using lodash .groupBy. how to add your own keys for grouped output?
But only thing is always I want to push the data from second array in index=1 of "info" and first one to index=0. If any of the array does not have a "type" then the "info" array should have empty/null values.
use _.mapValues to iterate object values with key accessing
var res = _.chain(array1)
.concat(array2)
.groupBy('type')
.mapValues(function(val, key) {
return {
type: key,
info: val
};
})
.values()
.value();
It's possible to achieve the result you want in javascript, or using helper like lodash.
The last part of your question is hard to understand. If an array doesn't have "type", how would you group them. Please provide clearer explanation or modify your expected input and output.
[Updated]
Thanks for your explanation. This is the solution using plain javascript.
// get uniques type from two arrays
const uniqueTypes = new Set(array1
.concat(array2)
.map(x => x.type));
// loop the types, find item in both array
// group it
let result = Array.from(uniqueTypes).reduce((acc, curr) => {
const item1 = array1.find(x => x.type === curr);
const item2 = array2.find(x => x.type === curr);
const info1 = item1 ? [item1] : [];
const info2 = item2 ? [item2] : [];
acc = acc.concat({ type: curr, info: [info1, info2] });
return acc;
}, []);
console.log(result);
jsbin here: https://jsbin.com/mobezogaso/edit?js,console
Here's a working solution :). Hope it helps!
var array1 = [
{
"type":"test",
"name":"name1"
},
{
"type":"dev",
"name":"name2"
}
]
var array2 = [
{
"type":"test",
"name":"name3"
},
{
"type":"dev",
"name":"name4"
},
{
"type":"prod",
"name":"name5"
}
]
var newArray = array1.concat(array2);
var arr1 = [];
var arr2 = [];
var arr3 = [];
var arrTypes = [];
var finalArray = [];
var someArray = [];
for(var i in newArray)
{
if (arrTypes.indexOf(newArray[i].type) === -1){
arrTypes.push(newArray[i].type);
}
if(newArray[i].type === "test"){
arr1.push(newArray[i]);
}
else if(newArray[i].type === "dev"){
arr2.push(newArray[i]);
}
else if(newArray[i].type === "prod"){
arr3.push(newArray[i]);
}
}
someArray.push(arr1);
someArray.push(arr2);
someArray.push(arr3);
for(var j = 0; j < someArray.length; j++){
finalArray.push({
"type": arrTypes[j],
"info": someArray[j]
});
}
console.log(finalArray);
And a short (unreadable?) ES6 solution:
Concat the arrays
Reduce the array into a Map object, with the type as the key
Get the entries iterator - key (type) - value (array of objects)
Use spread to convert the entry iterator to an array
Array#Map the array of entries to the type/info objects
const array1 = [{"type":"test","name":"name1"},{"type":"dev","name":"name2"}];
const array2=[{"type":"test","name":"name3"},{"type":"dev","name":"name4"},{"type":"prod","name":"name5"}];
const result = [...array1.concat(array2).reduce((r, o) => {
r.has(o.type) ? r.get(o.type).push(o) : r.set(o.type, [o]);
return r;
}, new Map).entries()]
.map(([type, info]) => ({
type, info
}));
console.log(result);
This question already has answers here:
Simplest code for array intersection in javascript
(40 answers)
Closed 3 years ago.
I have two arrays, and I want to be able to compare the two and only return the values that match. For example both arrays have the value cat so that is what will be returned. I haven't found anything like this. What would be the best way to return similarities?
var array1 = ["cat", "sum","fun", "run"];
var array2 = ["bat", "cat","dog","sun", "hut", "gut"];
//if value in array1 is equal to value in array2 then return match: cat
You can use :
const intersection = array1.filter(element => array2.includes(element));
Naturally, my approach was to loop through the first array once and check the index of each value in the second array. If the index is > -1, then push it onto the returned array.
Array.prototype.diff = function(arr2) {
var ret = [];
for(var i in this) {
if(arr2.indexOf(this[i]) > -1){
ret.push(this[i]);
}
}
return ret;
};
My solution doesn't use two loops like others do so it may run a bit faster. If you want to avoid using for..in, you can sort both arrays first to reindex all their values:
Array.prototype.diff = function(arr2) {
var ret = [];
this.sort();
arr2.sort();
for(var i = 0; i < this.length; i += 1) {
if(arr2.indexOf(this[i]) > -1){
ret.push(this[i]);
}
}
return ret;
};
Usage would look like:
var array1 = ["cat", "sum","fun", "run", "hut"];
var array2 = ["bat", "cat","dog","sun", "hut", "gut"];
console.log(array1.diff(array2));
If you have an issue/problem with extending the Array prototype, you could easily change this to a function.
var diff = function(arr, arr2) {
And you'd change anywhere where the func originally said this to arr2.
I found a slight alteration on what #jota3 suggested worked perfectly for me.
var intersections = array1.filter(e => array2.indexOf(e) !== -1);
Hope this helps!
This function runs in O(n log(n) + m log(m)) compared to O(n*m) (as seen in the other solutions with loops/indexOf) which can be useful if you are dealing with lots of values.
However, because neither "a" > 1 nor "a" < 1, this only works for elements of the same type.
function intersect_arrays(a, b) {
var sorted_a = a.concat().sort();
var sorted_b = b.concat().sort();
var common = [];
var a_i = 0;
var b_i = 0;
while (a_i < a.length
&& b_i < b.length)
{
if (sorted_a[a_i] === sorted_b[b_i]) {
common.push(sorted_a[a_i]);
a_i++;
b_i++;
}
else if(sorted_a[a_i] < sorted_b[b_i]) {
a_i++;
}
else {
b_i++;
}
}
return common;
}
Example:
var array1 = ["cat", "sum", "fun", "hut"], //modified for additional match
array2 = ["bat", "cat", "dog", "sun", "hut", "gut"];
intersect_arrays(array1, array2);
>> ["cat", "hut"]
Loop through the second array each time you iterate over an element in the first array, then check for matches.
var array1 = ["cat", "sum", "fun", "run"],
array2 = ["bat", "cat", "dog", "sun", "hut", "gut"];
function getMatch(a, b) {
var matches = [];
for ( var i = 0; i < a.length; i++ ) {
for ( var e = 0; e < b.length; e++ ) {
if ( a[i] === b[e] ) matches.push( a[i] );
}
}
return matches;
}
getMatch(array1, array2); // ["cat"]
var array1 = [1, 2, 3, 4, 5, 6];
var array2 = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var array3 = array2.filter(function(obj) {
return array1.indexOf(obj) !== -1;
});
You can use javascript function .find()
As it says in MDN, it will return the first value that is true. If such an element is found, find immediately returns the value of that element. Otherwise, find returns undefined.
var array1 = ["cat", "sum", "fun", "run", "cat"];
var array2 = ["bat", "cat", "dog", "sun", "hut", "gut"];
found = array1.find((val, index) => {
console.log('index', index) // Stops at 0
return array2.includes(val)
})
console.log(found)
Or use .filter(), which loops through every elements first, then give back the result to you.
var array1 = ["cat", "sum", "fun", "run", "cat"];
var array2 = ["bat", "cat", "dog", "sun", "hut", "gut"];
found = array1.filter((val, index) => {
console.log('index', index) // Stops at array1.length - 1
return array2.includes(val)
})
console.log(found)
use lodash
GLOBAL.utils = require('lodash')
var arr1 = ['first' , 'second'];
var arr2 = ['second '];
var result = utils.difference(arr1 , arr2);
console.log ( "result :" + result );
Libraries like underscore and lodash have a utility method called intersection to find matches in arrays passed in. Take a look at: http://underscorejs.org/#intersection
Done as a answer so I can do formatting...
This is the the process you need to go through. Looping through an array for the specifics.
create an empty array
loop through array1, element by element. {
loop through array2, element by element {
if array1.element == array2.element {
add to your new array
}
}
}
If your values are non-null strings or numbers, you can use an object as a dictionary:
var map = {}, result = [], i;
for (i = 0; i < array1.length; ++i) {
map[array1[i]] = 1;
}
for (i = 0; i < array2.length; ++i) {
if (map[array2[i]] === 1) {
result.push(array2[i]);
// avoid returning a value twice if it appears twice in array 2
map[array2[i]] = 0;
}
}
return result;
With some ES6:
let sortedArray = [];
firstArr.map((first) => {
sortedArray[defaultArray.findIndex(def => def === first)] = first;
});
sortedArray = sortedArray.filter(v => v);
This snippet also sorts the firstArr based on the order of the defaultArray
like:
let firstArr = ['apple', 'kiwi', 'banana'];
let defaultArray = ['kiwi', 'apple', 'pear'];
...
console.log(sortedArray);
// ['kiwi', 'apple'];
Iterate on array1 and find the indexof element present in array2.
var array1 = ["cat", "sum","fun", "run"];
var array2 = ["bat", "cat","sun", "hut", "gut"];
var str='';
for(var i=0;i<array1.length;i++){
if(array2.indexOf(array1[i]) != -1){
str+=array1[i]+' ';
};
}
console.log(str)
I am trying to sort one array, but have a second array stay in sync with the first.
Example:
var a1 = ["human", "animal", "plant"];
var a2 = ["person", "beast", "nature"];
a1.sort();
After the sort I need to arrays to look like this:
a1 = ["animal", "human", "plant"];
a2 = ["beast", "person", "nature"];
Is there an easy way to do this, Maybe using a custom sort function?
You could zip the arrays before sorting, and unzip them after sorting:
var a = ["human", "animal", "plant"],
b = ["person", "beast", "nature"],
zipped = [];
// zip
for (var i=0; i<a.length; i++)
{
zipped.push({a: a[i], b: b[i]});
}
zipped.sort(function (x, y)
{
return x.a - y.a;
});
// unzip
var z;
for (i=0; i<zipped.length; i++)
{
z = zipped[i];
a[i] = z.a;
b[i] = z.b;
}
...but I think #duffymo's got a better suggestion for you. Use an object/hash/associative array/map.
var a = [{key: 'human', value: 'person'},
{key: 'animal', value: 'beast'},
{key: 'plant', value: 'nature'}];
a.sort(function (x, y)
{
return x.key - y.key;
});
Try something like this (untested):
a1.sort(function(a, b) {
if (a > b) {
// swap a2[0] and a2[1]
var tmp = a2[0];
a2[0] = a2[1];
a2[1] = tmp;
return 1
} else if (a < b) {
return -1
} else {
return 0
}
});
Live DEMO
Something like that, play around with the return values to get it perfect
I'd use an associative array and sort the keys. That's what you've got here. I think an associative array is a better encapsulation of the idea.