var array1 = ["ddd","aaa","eee","aaa","fff","bbb","ggg","aaa","ccc","fff"]
i have to arrange it in a way that identical values has to be placed together
output array should be
["ddd","aaa","aaa","aaa","eee","fff","fff","bbb","ggg","ccc"]
how to write the logic for this one ??
You could iterate the array and check the position and if not the same as the actual element, splice the value to the earlier position.
var array = ["ddd","aaa","eee","aaa","fff","bbb","ggg","aaa","ccc","fff"],
i = 0, p;
while (i < array.length) {
p = array.indexOf(array[i]);
if (p !== i) {
array.splice(p, 0, array.splice(i, 1)[0]);
}
i++;
}
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Sort array using sort() method like this
var array1 = ["ddd","aaa","eee","aaa","fff","bbb","ggg","aaa","ccc","fff"];
console.log(array1.sort());
Well actually for you request .sort() might be an overkill. You can simply do this by;
function quasiSort(a){
var h = a.reduce((h,e) => h[e] ? (h[e].push(e), h)
: (h[e] = [e], h), {});
return Object.keys(h).reduce((r,k) => r.concat(h[k]),[]);
}
var array1 = ["ddd","aaa","eee","aaa","fff","bbb","ggg","aaa","ccc","fff"];
console.log(quasiSort(array1));
You can create one object to store values and index and then use that object to create new array.
var array1 = ["ddd","aaa","eee","aaa","fff","bbb","ggg","aaa","ccc","fff"],
obj = {}, i = 0
array1.forEach(function(e) {
if(!obj[e]) obj[e] = {index: i++, values: []}
obj[e].values.push(e)
})
var result = [].concat(...Object.keys(obj).reduce((r, e) => (r[obj[e].index] = obj[e].values, r), []))
console.log(result)
Related
I would like to get find elements having same characters but in different order in an array. I made javascript below,is there any way to create Javascript function more basic? Can you give me an idea? Thank you in advance..
<p id="demo"></p>
<script>
const arr1 = ["tap", "pat", "apt", "cih", "hac", "ach"];
var sameChars = 0;
var subArr1 = [];
for(var i = 0; i < arr1.length; i++){
for(var j = i+1; j < arr1.length; j++){
if(!subArr1.includes(arr1[i]) && !subArr1.includes(sortAlphabets(arr1[i]))){
subArr1.push(arr1[i]);
sameChars++;
}
if(sortAlphabets(arr1[i]) == sortAlphabets(arr1[j])){
if(!subArr1.includes(arr1[j])){
subArr1.push(arr1[j]);
}
}
}
}
function sortAlphabets(text1) {
return text1.split('').sort().join('');
};
document.getElementById("demo").innerHTML = sameChars;
</script>
I would just use reduce. Loop over split the string, sort it, join it back. Use it as a key in an object with an array and push the items onto it.
const arr1 = ["tap", "pat", "apt", "cih", "hac", "ach"];
const results = arr1.reduce((obj, str) => {
const key = str.split('').sort().join('');
obj[key] = obj[key] || [];
obj[key].push(str);
return obj;
}, {});
console.log(Object.values(results));
You can get the max frequency value by building a map and getting the max value of the values.
const frequencyMap = (data, keyFn) =>
data.reduce(
(acc, val) =>
(key => acc.set(key, (acc.get(key) ?? 0) + 1))
(keyFn(val)),
new Map());
const groupMap = (data, keyFn) =>
data.reduce(
(acc, val) =>
(key => acc.set(key, [...(acc.get(key) ?? []), val]))
(keyFn(val)),
new Map());
const
data = ["tap", "pat", "apt", "cih", "hac", "ach"],
sorted = (text) => text.split('').sort().join(''),
freq = frequencyMap(data, sorted),
max = Math.max(...freq.values()),
groups = groupMap(data, sorted);
document.getElementById('demo').textContent = max;
console.log(Object.fromEntries(freq.entries()));
console.log(Object.fromEntries(groups.entries()));
.as-console-wrapper { top: 2em; max-height: 100% !important; }
<div id="demo"></div>
Maybe split the code into two functions - one to do the sorting and return a new array, and another to take that array and return an object with totals.
const arr = ['tap', 'pat', 'apt', 'cih', 'hac', 'ach'];
// `sorter` takes an array of strings
// splits each string into an array, sorts it
// and then returns the joined string
function sorter(arr) {
return arr.map(str => {
return [...str].sort().join('');
});
}
// `checker` declares an object and
// loops over the array that `sorter` returned
// creating keys from the strings if they don't already
// exist on the object, and then incrementing their value
function checker(arr) {
const obj = {};
for (const str of arr) {
// All this line says is if the key
// already exists, keep it, and add 1 to the value
// otherwise initialise it with 0, and then add 1
obj[str] = (obj[str] || 0) + 1;
}
return obj;
}
// Call `checker` with the array from `sorter`
console.log(checker(sorter(arr)));
<p id="demo"></p>
Additional documentation
map
Loops and iteration
Spread syntax
I have something like this, an array of arrays where each array has a 7 values
const arrays = [[1,2,3,4,5,6,7],[8,9,10,11,12,13,14]]
What's the most efficient way to split this into array of arrays where each array will have a 2 values and last array of arrays will hold the remaining 1 element, like this
[[1,2], [8,9]] [[3,4], [10,11]] [[5,6], [12,13]] [[7], [14]]
You can use array#reduce and array#forEach to split your array based on size.
const arr = [[1,2,3,4,5,6,7],[8,9,10,11,12,13,14]],
size = 2,
result = arr.reduce((r, a, i) => {
a.forEach((v,j) => {
const idx = Math.floor(j/size);
r[idx] = r[idx] || [];
r[idx][i] = r[idx][i] || [];
r[idx][i].push(v);
});
return r;
},[]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
It doesn't look that efficient, but it works.
const arrays = [[1,2,3,4,5,6,7],[8,9,10,11,12,13,14]];
// number of sub arrays
var numsubarr = Math.ceil(arrays[0].length / 2);
// parring up the vaules
var arr1 = arrays.map(arr => Array.from(Array(numsubarr).keys()).map(i => arr.slice(i*2, i*2+2)));
// combining the two arrays
var arr2 = Array.from(Array(numsubarr).keys()).map(i => [arr1[0][i],arr1[1][i]]);
console.log(arr2);
How can I initialize an empty vector in JavaScript, but in a way that it has X positions? For this I had to make a loop and set some values for the positions of the vector. I want a more correct way to do it.
let values: [],
for (i = 0; i < x; i++) {
this.state.values[i] = '';
}
Here are some short and elegant ways on top of my mind:
Array.from(Array(size), () => value)
Array.from({ length: size }, () => value)
Array(arraySize).fill(value);
You can use:
new Array(x);
To produce an array with x empty values.
You can then map it by expanding the array:
[...new Array(x)].map(_=>/*your code*/);
You can mix the following Array and create a static filledArray function on the Array object.
new Array(size)
Array.prototype.fill
Array.from
if (Array.filledArray === undefined) {
Array.filledArray = function(size, defaultValue, start, end) {
return (arr => Array.prototype.fill.apply(arr, Array.from(arguments).slice(1)))(new Array(size));
}
}
let values = Array.filledArray(7, 'foobar');
console.log(values);
.as-console-wrapper { top: 0; max-height: 100% !important;}
I have an array of objects, and want to:
Remove certain objects from the array
Treat the removed objects in a second step
I don't know in advance where these objects are. To recognize them, I need to use a function that queries their properties. It makes sense to retrieve the removed objects in a second array.
I had hoped to find a native method like filter or splice that would do this. Here's what I've come up with as a solution:
if (!Array.prototype.cherrypick) {
Array.prototype.cherrypick = function(fn) {
let basket = []
let ii = this.length
let item
for ( ; ii-- ; ) {
item = this[ii]
if (fn(item)) {
basket.unshift(item)
this.splice(ii, 1)
}
}
return basket
}
}
Have I missed something? Is there a native method that does this already? Is my solution unsound in some way?
Have I missed something? Is there a native method that does this already?
No, most native utility methods try not to mutate the array and instead return a new one.
Is my solution unsound in some way?
Using splice and unshift repeatedly like you do is very inefficient. Better write
if (typeof Array.prototype.cherrypick == "function")
console.warn("something already defines Array#cherrypick!");
Array.prototype.cherrypick = function(predicate) {
let removed = [];
for (let i=0, j=0; i<this.length; i++) {
const item = this[i];
if (fn(item)) {
removed.push(item);
} else {
this[j++] = item; // keep in array, but at new position
}
}
this.length = j; // removes rest
return removed;
};
Methods such as Array.filter() returns a new array instead of changing the original array.
You can create a partition method using Array.reduce() that will return two arrays - those that passed the predicate, and those that failed:
const partition = (predicate, arr) =>
arr.reduce((r, o) => {
r[+!!predicate(o)].push(o);
return r;
}, [[], []]);
const arr = [4, 8, 3, 10, 12];
const result = partition(n => n > 5, arr);
console.log(result);
And you can use the partition logic with Array.splice() to create the cherrypick method:
if (!Array.prototype.cherrypick) {
Array.prototype.cherrypick = function(predicate) {
const [removedItems, items] = arr.reduce((r, o) => {
r[+!!predicate(o)].push(o);
return r;
}, [[], []]);
this.splice(0, arr.length, items);
return removedItems;
}
}
const arr = [4, 8, 3, 10, 12];
const removed = arr.cherrypick(n => n > 5);
console.log('arr ', arr);
console.log('removed ', removed);
Just filter twice:
const picked = array.filter(fn);
array = array.filter((el, i, a) => !fn(el, i, a));
Use reduce as follows :
array = [1,2,3,4,5,6,7];
fn = n => n % 3 == 0;
[array, picked] = array.reduce ( (r, el) => (r[+fn(el)].push (el), r), [[], []] )
Do you want something like this?
const basket = ['apple', 'banana', 'car'];
const filterMapBasket = basket
.filter(item => item !== 'car')
.map(item => {return { name: item }});
This will result the initial basket array of strings to be filtered and transformed to an array of objects.
This will alter the source array in place removing items meeting some test, and return those items...
Array.prototype.removeIf = function(fn) {
let i = this.length;
let removed = [];
while (i--) {
if (fn(this[i], i)) {
removed.push(...this.splice(i, 1));
}
}
return removed;
};
let a = [0,1,2,3,4,5];
let removed = a.removeIf(i => i%2);
console.log(a);
console.log(removed);
This question already has answers here:
Join sequence of arrays with array delimeters ("intersperse")
(7 answers)
Closed 5 years ago.
I have an array [1,2,3,4,5,6] and a separator '~' and I want to joint them into a new array with '~' being the separator.
I'd like the output to be [1,'~', 2,'~', 3,'~', 4,'~', 5,'~', 6].
Using Lodash I got something like:
var my_array = [1,2,3,4,5,6]
var separator = '~'
_.flatten(_.zip(my_array, new Array(my_array.length).fill(separator)))
But this feels ugly and I'm sure there is a better way.
EDIT: Even though the array above has ints I'd like this to work for any type of object.
Why not in pue Javascript:
Minor Update: to account for values greater then 9
first join it to a string my_array.join("~")
then split every char .split(/\b/gi)
var my_array = [1,2,3,4,5,6,10,11]
var separator = '~'
console.info(my_array.join("~").split(/\b/gi));
Update (even if closed):
In Regard to point, other Objects. This should work, even if not a one-liner.
var myArray = [1,2,3,45,6,10,new Date()];
var newArray = myArray.reduce((p,n)=>{
if(p.length){
p.push("~");
}
p.push(n);
return p;
},[]);
console.info(newArray)
Nice simple forEach without a dozen temporary arrays, etc.:
var my_array = [1,2,3,4,5,6];
var result = [my_array[0]];
my_array.forEach(function(entry, index) {
if (index > 0) {
result.push("~", entry);
}
});
console.log(result);
Or you can get rid of the if with a single temporary array:
var my_array = [1,2,3,4,5,6];
var result = [my_array[0]];
my_array.slice(1).forEach(function(entry, index) {
result.push("~", entry);
});
console.log(result);
Just throwing my hat in:
arr.map(x => [x, '~']).reduce((p, c) => p.concat(c));
This isn't very hacky, it maps every element into two elements and concats them together, it is pretty easy to generalize:
const intercalate = (arr, sep) => arr.map(x => [x, sep])
.reduce((p, c) => p.concat(c))
.slice(0, -1);
Or with a single reduce:
const intercalate = (arr, sep) => arr.reduce((p, c) => p.concat(c, sep)).slice(0, -1);
Here is an option using forEach -
var a = [1,2,3]
var sep = '~'
var b = []
a.forEach(function(x) { b.push(x, sep) })
b.pop() // remove the last `~`
Using _.flatMap,
var my_array = [1,2,3,4,5,6];
var separator = '~';
console.log(_.flatMap(my_array, function( v ){ return [v,separator] }).slice(0,-1));
Update:
Ensure trailing ~ is removed.
Using a traditional for loop
var nums = [1,2,3,4,5,6];
var dash = '~';
var res = [];
for (var i=0; i<nums.length; i++){
res.push(nums[i]);
res.push(dash);
}
res.pop();
console.log(res);
You could use Array#reduce and concat a tilde if necessary.
var array = [1, 2, 3, 4, 5, 6],
result = array.reduce(function (r, a, i) {
return r.concat(i ? '~' : [], a);
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Anosther proposal with Array#forEach
var array = [1, 2, 3, 4, 5, 6],
result = [];
array.forEach(function (a) {
result.push(a, '~');
});
result.length--;
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }