Is there any method to combine the pair inside array to form a new array in java script - javascript

I am trying to arrange any kind of array input into a sorted array that also combines the equal pairs into an array inside the same array.
I do the following
const arrangeTheArray=(arr)=>
{
//checking input here
if(arr.length<2)
{
return arr;
} else {
//sorting the array
arr= arr.sort();
}
//displaying the sorted array
console.log(arr);
for(let i=1; i<arr.length;i++)
{
for(let j=0;j<i;j++)
{
//here I am looping and comparing the values of array
if(arr[j]===arr[i]){
//putting the value
arr[j]= [arr[i],arr[j]];
}
}
}
//displaying the final output
console.log(arr);
}
arrangeTheArray([0,2,2,1,1,6,3,1,0])
e.g array input : [0,2,2,1,1,6,3,1,0]
final out put: [[0,0],[1,1,1],[2,2],3,6]

You can use reduce and map.
Here idea is
First create a object with each digit as key and group the values by key.
Now map on the grouped data, if the length of element greater than one pass element as it is, else pass the 0th index value
let combine = (arr) =>{
let groups = arr.reduce((op,inp)=>{
op[inp] = op[inp] || []
op[inp].push(inp)
return op
},{})
let final = Object.values(groups).map(e=> e.length > 1 ? e : e[0])
return final
}
console.log(combine([0,2,2,1,1,6,3,1,0]))
const arrangeTheArray=(arr)=>{
if(arr.length<2)
{
return arr;
} else {
arr = arr.sort((a,b)=>a-b);
}
let final = []
for(let i=0;i<arr.length;i++){
let current = arr[i]
let j = i;
let temp = []
while(arr[j] === current){
temp.push(arr[j])
j++
}
i = j-1
temp = temp.length > 1 ? temp : temp[0]
final.push(temp)
}
console.log(final)
}
arrangeTheArray([0,2,2,1,1,6,3,1,0])

You can use Array.reduce to accumulate the common elements in an object.
Then use Object.values and Array.from to process the nested arrays into arrays of common elements and distinct elements:
const arrangeTheArray = (arr) => {
if (!Array.isArray(arr) && arr.length < 2){
return arr;
}
const pairs = arr.reduce((acc, ele) => {
if(acc[ele]){
acc[ele].push(ele);
}else{
acc[ele] = [ele];
}
return acc;
}, {});
return Array.from(Object.values(pairs), ele => ele.length > 1 ? ele : +ele.join())
}
console.log(arrangeTheArray([0,2,2,1,1,6,3,1,0]));

You could sort the array with a callback for numbers and reduce the array by checking the predecessor p and the actual value v and push either the value or an array of the last group and the value.
function arrangeTheArray(array) {
return array
.sort((a, b) => a - b)
.reduce(
(r, v, i, { [i - 1]: p }) => r.concat([p !== v ? v : [].concat(r.pop(), v)]),
[]
);
}
console.log(arrangeTheArray([0, 2, 2, 1, 1, 6, 3, 1, 0]));
.as-console-wrapper { max-height: 100% !important; top: 0; }
With a classsic while loop from the end, because the array shrinks.
function arrangeTheArray(array) {
var i = array.length - 1;
array.sort((a, b) => a - b);
while (i--) {
if (array[i] === (Array.isArray(array[i + 1]) ? array[i + 1][0] : array[i + 1])) {
array[i] = [].concat(array[i], ...array.splice(i + 1, 1));
}
}
return array;
}
console.log(arrangeTheArray([0, 2, 2, 1, 1, 6, 3, 1, 0]));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

Inconsistency, when returning index of duplicate values

I'm trying to create an algorithm to find duplicate values in a list and return their respective indexes, but the script only returns the correct value, when I have 2 equal elements:
array = [1,2,0,5,0]
result -> (2) [2,4]
Like the example below:
array = [0,0,2,7,0];
result -> (6) [0, 1, 0, 1, 0, 4]
The expected result would be [0,1,4]
Current code:
const numbers = [1,2,0,5,0];
const checkATie = avgList => {
let averages, tie, n_loop, currentAverage;
averages = [... avgList];
tie = [];
n_loop = 0;
for(let n = 0; n <= averages.length; n++) {
currentAverage = parseInt(averages.shift());
n_loop++
for(let avg of averages) {
if(avg === currentAverage) {
tie.push(numbers.indexOf(avg),numbers.indexOf(avg,n_loop))
};
};
};
return tie;
}
console.log(checkATie(numbers));
if possible I would like to know some way to make this code more concise and simple
Use a Set
return [...new Set(tie)]
const numbers1 = [1,2,0,5,0];
const numbers2 = [0,0,2,7,0];
const checkATie = avgList => {
let averages, tie, n_loop, currentAverage;
averages = [... avgList];
tie = [];
n_loop = 0;
for(let n = 0; n <= averages.length; n++) {
currentAverage = parseInt(averages.shift());
n_loop++
for(let avg of averages) {
if(avg === currentAverage) {
tie.push(avgList.indexOf(avg),avgList.indexOf(avg,n_loop))
};
};
};
return [...new Set(tie)]
}
console.log(checkATie(numbers1));
console.log(checkATie(numbers2));
I hope this help you.you can use foreach function to check each item of array
var array = [0,0,2,7,0];
var result = [] ;
array.forEach((item , index)=>{
if(array.findIndex((el , i )=> item === el && index !== i ) > -1 ){
result.push(index)
}
})
console.log(result);
//duplicate entries as an object
checkDuplicateEntries = (array) => {
const duplicates = {};
for (let i = 0; i < array.length; i++) {
if (duplicates.hasOwnProperty(array[i])) {
duplicates[array[i]].push(i);
} else if (array.lastIndexOf(array[i]) !== i) {
duplicates[array[i]] = [i];
}
}
console.log(duplicates);
}
checkDuplicateEntries([1,2,0,5,0]);
// hope this will help
Create a lookup object with value and their indexes and then filter all the values which occurred more than once and then merge all indexes and generate a new array.
const array = [1, 2, 0, 5, 0, 1, 0, 2],
result = Object.values(array.reduce((r, v, i) => {
r[v] = r[v] || [];
r[v].push(i);
return r;
}, {}))
.filter((indexes) => indexes.length > 1)
.flatMap(x => x);
console.log(result);

Optimize Time Complexity For Odd Occurrences In Array

I have this code that pairs same elements in an array, with the expectation that the array will have an odd length and it should return the only element that couldn't get a pair. So I wrote the code just well, and it works fine for smaller arrays, but with very large big integers of over 1 billion, the time complexity became O(N**2) and then the need to refactor my code to get a much better performance for large arrays and large array elements. Here is my code below;
function solution(A) {
if(!Array.isArray(A)) return 0;
var temp = new Array(A.length);
var position = 0;
for(let i=0; i<A.length; i++){
if(temp.includes(A[i])){
position = temp.indexOf(A[i]);
index = A.indexOf(A[i]);
delete temp[position];
delete A[index];
delete A[i];
}else{
temp[i] = A[i];
}
}
for(let j=0; j<A.length; j++){
if(A[j] !== undefined) return A[j];
else continue;
}
}
To test it, source data can look like [2,3,6,7,3,5,5,6,2] and it will give an output of 7. But when the array is so large up to [1,2,....] with length n = n=999,999, or n = 5000,000,000, the time complexity increases exponentially.
You might use Object to store non-paired elements only.
Please note that you don't need to store all the array elements and their counts in the Object and then filter by count (like #StepUp does).
Everything's been done in a single loop.
The function returns Array of all non-paired elements:
const solution = A => Array.isArray(A) ?
Object.keys(
A.reduce((r, k) => {
r[k] = r[k] || 0;
if (++r[k] > 1) delete r[k];
return r;
}, {})
) : [];
console.log(solution([2, 3, 6, 7, 3, 5, 5, 6, 2]))
We can try to find odd occurrences for one iteration by using great features of object. Object is key - value pair. So access to object key is O(1). So when we meet the same element, then we just increment value:
const hashMap = arr.reduce((a, c)=> {
a[c] = a[c] || 0;
a[c] += 1;
return a;
},{})
const result = Object.keys(hashMap).filter(key => hashMap[key] === 1);
An example:
let arr = [2, 3, 6, 7, 3, 5, 5, 6, 2];
const hashMap = arr.reduce((a, c)=> {
a[c] = a[c] || 0;
a[c] += 1;
return a;
},{})
const result = Object.keys(hashMap).filter(key => hashMap[key] === 1);
console.log(result);
My two 100% JavaScript solutions with optimized time complexity. The first one is using Set:
function solution(A) {
const pairs = new Set();
for (const num of A) {
if (pairs.has(num)) {
pairs.delete(num);
} else {
pairs.add(num);
}
}
const [unpaired] = pairs;
return unpaired;
}
The second one is using bitwise XOR:
function solution(A) {
let unpaired;
for (const num of A) {
unpaired ^= num;
}
return unpaired;
}

how to print a unique number in a array

The problem is to find the unique number in a array such as [2,2,2,5].
The output should be 5 as it is the 1 unique element in the array.
I have attempted this:
function findUniq(arr) {
var b= arr[0];
var c;
for(var i=0; i<arr.length; i++)
{
if(arr[i]===b )
{
b=arr[i]
}
else
{
c=arr[i];
}
}
return c
console.log(findUniq([3, 5, 3, 3, 3]))
This works fine unless the unique number is the first element in the array. How do I fix this?
You can use indexOf and lastIndexOf to see if a value occurs more than once in the array (if it does, they will be different), and if so, it is not the unique value. Use filter to process the array:
let array = [2,2,2,5];
console.log(array.filter(v => array.indexOf(v) === array.lastIndexOf(v)));
array = [5,3,3,3,3];
console.log(array.filter(v => array.indexOf(v) === array.lastIndexOf(v)));
array = [4,4,5,4];
console.log(array.filter(v => array.indexOf(v) === array.lastIndexOf(v)));
You can create a recursive function that will take the first element of the array and see if it exists in the rest of it, if it does, it will take the next element and do the same, return the element if it doesn't exist in the rest of the array :
const arr = [3, 3, 3, 5, 3];
const find = arr => {
const [f, ...rest] = arr;
if(rest.includes(f))
return find(rest);
else
return f;
}
const result = find(arr);
console.log(result);
Note that this will return the last element if all of them are the same [3,3,3] will return 3
Try something like this using a set, which only stores unique elements:
var set = new Set(arr);
// count instances of each element in set
result = {};
for(var i = 0; i < a.length; ++i) {
if(!result[arr[i]])
result[arr[i]] = 0;
++result[arr[i]];
}
for (var value in result) {
if (value == 1) {
return value;
}
}
// if there isn't any
return false;
This should work, please tell me if it doesn't.
This is another implementation that is surely less efficient than that of #Nick's, but it is a valid algorithm anyway:
function findUniq(arr) {
var elemCount = new Map();
var uniq = [];
// Initialize elements conts
for (var k of arr.values()) {
elemCount.set(k, 0);
}
// Count elements
for (var k of arr.values()) {
elemCount.set(k, elemCount.get(k) + 1);
}
// Add uniq elements to array
for (var [k, v] of elemCount.entries()) {
if (v === 1) uniq.push(k);
}
return uniq;
}
console.log(findUniq([3, 5, 3, 3, 3]))
if you prefer .reduce over .map for your use case (for performance/etc. reasons):
function existance(data) {
return data.reduce((a, c) => (data.indexOf(c) === data.lastIndexOf(c)) ? a.concat(c) : a, []);
}
console.log(existance([1,1,1,2]));
console.log(existance([1,1,2,3,4,5,5,6,6,6]));

looping through javascript object without sorting based on keys

this is the problem description:
Given an array of integers, calculate the fractions of its elements that are positive, negative, and are zeros. Print the decimal value of each fraction on a new line.
for example given the array arr=[1,1,0,-1,-1] output should be:
0.400000
0.400000
0.200000
I know there is more more simple solution for it ,and i am sorry for my silly simple question but i wanna make my code work, my code sorts the output based on the key and removes duplicates. for this arr, my code output is:
0.200000
0.400000
thank you so much in advance for any help.
function plusMinus(arr) {
var freq = {};
for (var i = 0; i < arr.length; i++){
if (freq[arr[i]]) {
freq[arr[i]]++;
} else {
freq[arr[i]] = 1;
}
} for(var key in freq){
console.log((freq[key]/arr.length).toFixed(6));
}
}
You could take an object with predifined properties, this prevents each loop for checking the existence and take an array of keys for getting the result in a wanted order.
function plusMinus(arr) {
var freq = { 1: 0, '-1': 0, 0: 0 },
i, key;
for (i = 0; i < arr.length; i++) {
freq[arr[i]]++;
}
for (key of [1, -1, 0]) {
console.log((freq[key] / arr.length).toFixed(6));
}
}
plusMinus([1, 1, 0, -1, -1]);
Let's make sure the order of key in the map by defining it first.
function plusMinus(arr) {
var freq = {
posetive: 0,
negative: 0,
zero: 0
};
for (var i = 0; i < arr.length; i++){
if( arr[i] < 0) {
freq.negative++;
} else if(arr[i] > 0) {
freq.posetive++;
} else {
freq.zero++;
}
}
for(var key in freq){
console.log((freq[key]/arr.length).toFixed(6));
}
}
plusMinus([1,1,0,-1,-1]);
You can use reduce.
Here idea is
First loop through original array and check for the value.
If value is zero we increment count of zero key.
If value is positive we increment count of pos key.
If value is negative we increment count of neg key.
Finally we divide each count by length of array.
let arr = [1,1,0,-1,-1]
let op = arr.reduce((op,inp)=>{
if(inp === 0){
op.zero.count++
} else if (inp > 0){
op.pos.count++;
} else {
op.neg.count++;
}
return op
},{zero:{count:0},pos:{count:0},neg:{count:0}})
let final = Object.entries(op).map(([key,value])=>({
[key] : value.count / arr.length
}))
console.log(final)
Use reduce, map and filter:
const arr = [1, 1, 0, -1, -1];
const counts = arr.reduce((acc, curr) => {
if (!curr) acc[0]++;
else if (curr > 0) acc[1]++;
else acc[2]++;
return acc
}, [0, 0, 0]);
const result = counts.map(e => e / arr.length).filter((e, i, a) => a.indexOf(e) == i);
console.log(result);
You can try using Array.reduce and the resulting array will have the fraction of positive number at the '0'th index, negative at '1'st and zero at the '2'nd index.
Now if you want to control the count of the number of elements after decimal point, use Array.map at the end to transform it.
const array = [1,1,0,-1,-1];
function plusMinus(arr){
const output = arr.reduce((acc, ele) => {
if(ele > 0){
acc[0] = ((acc[0] || 0 ) + 1 / arr.length);
}
if(ele < 0){
acc[1] = ((acc[1] || 0 ) + 1 / arr.length);
}
if(ele === 0) {
acc[2] = ((acc[2] || 0 ) + 1 / arr.length);
}
return acc;
}, []).map(ele => ele.toFixed(6));
console.log(...output);
}
plusMinus(array);
Math.sign is your friend here.
Math.sign
Also lodash would really help this snippet to be cleaner, I highly recommend _.countBy. Lodash .countBy
Here's the code.
const plusMinus = (numbers) => {
// Count by Sign (-1, 0 1)
const countSign = _.countBy(numbers, Math.sign);
// _.countBy return object, of counted { '1': 2, '0': 1, '-1': 2 }
// Print them in orders
const printOrder = [1, -1, 0];
printOrder.forEach(sign => {
console.log((countSign[sign] / numbers.length).toFixed(6));
});
}
const testArr = [1,1,0,-1,-1];
plusMinus(testArr);
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.11/lodash.min.js"></script>
Here is another one-line solution using Array.reduce() and Array.forEach() functions:
const plusMinus = arr => arr
.reduce((res, curr) => ++res[!curr ? 2 : curr < 0 ? 1 : 0] && res, [0, 0, 0])
.forEach(i => console.log((i / arr.length).toFixed(6)));
plusMinus([1, 1, 0, -1, -1]);

use lodash to remove elements from nested array form start and from end

I have one nested array for example
var arr = [
[0,1,2,3,4],
[0,1,2,3],
[0,1,2,3,4],
[0,1]
];
How to remove N items from end or from beginning using lodash?
For example if I remove 6 elements from beginning, I want result to be:
var arr = [
[1,2,3],
[0,1,2,3,4],
[0,1]
];
and if I remove 1 from end, I need result to be:
var arr = [
[0,1,2,3,4],
[0,1,2,3],
[0,1,2,3,4],
[0]
];
I hope i was clear. Lodash is not necessary.
This is my code:
function removeFromTop(group, count) {
for (var i = 0; i < group.length; i++) {
for (var x = 0; x < group[i].chatItems.length; x++) {
if(count) {
group[i].chatItems.splice(x, 1);
if(!group[i].chatItems.length) {
group.splice(i, 1);
};
count--;
} else {
break;
}
};
};
return group;
}
function removeFromBottom(group, count) {
for (var i = group.length - 1; i >= 0; i--) {
for (var x = group[i].chatItems.length - 1; x >= 0; x--) {
if(count) {
group[i].chatItems.splice(x, 1);
if(!group[i].chatItems.length) {
group.splice(i, 1);
};
count--;
} else {
break;
}
};
};
return group;
}
You could shift the inner array for each item count from the beginning and pop the values from the end. For the first you could use Array#reduce and for the other Array#reduceRight
function removeFromStart(array, n) {
var copy = JSON.parse(JSON.stringify(array));
return copy.reduce(function (r, a) {
while (n && a.length) {
a.shift();
n--;
}
a.length && r.push(a);
return r;
}, []);
}
function removeFromEnd(array, n) {
var copy = JSON.parse(JSON.stringify(array));
return copy.reduceRight(function (r, a) {
while (n && a.length) {
a.pop();
n--;
}
a.length && r.push(a);
return r;
}, []).reverse();
}
var array = [[0, 1, 2, 3, 4], [0, 1, 2, 3], [0, 1, 2, 3, 4], [0, 1]];
console.log(JSON.stringify(removeFromStart(array, 6)));
console.log(JSON.stringify(removeFromEnd(array, 6)));
.as-console-wrapper { max-height: 100% !important; top: 0; }
using Lodash function .drop you can drop very first element(s) of an array or else can specify n element(s) default value is 1. same way .dropRight for the end element(s).
var arr = [
[0,1,2,3,4],
[0,1,2,3],
[0,1,2,3,4],
[0,1]
];
// remove 1 element front of 2D Array
var resultFront= arr.map(function(value,index) { return _.drop(value); });
console.log(resultFront);
// remove 1 element from End of 2D Array
var resultEnd= arr.map(function(value,index) { return _.dropRight(value); });
console.log(resultEnd);
// remove 1 element front and end of 2D Array
var resultFrontEnd = arr.map(function(value,index) { return _.dropRight(_.drop(value)); });
console.log(resultFrontEnd);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
var arr = [
[0,1,2,3,4],
[0,1,2,3],
[0,1,2,3,4],
[0,1]
];
console.log(arr);
console.log('------------------------');
// remove 1 element front of 2D Array
var resultFront= arr.map(function(value,index) { return _.drop(value); });
console.log('Remove 1 element from front') ;
console.log(resultFront);
// remove 1 element from End of 2D Array
var resultEnd= arr.map(function(value,index) { return _.dropRight(value); });
console.log('Remove 1 element from end') ;
console.log(resultEnd);
// remove 1 element front and end of 2D Array
var resultFrontEnd = arr.map(function(value,index) { return _.dropRight(_.drop(value)); });
console.log('Remove 1 element from front & End') ;
console.log(resultFrontEnd);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
You can simply do as follows;
var arr = [[0,1,2,3,4],[0,1,2,3],[0,1,2,3,4],[0,1]],
r = [],
n = 6,
res = arr.reduce((r,sa) => r.n > sa.length ? (r.n -= sa.length, r)
: (r.push(sa.slice(r.n)), r.n = 0, r), (r.n = n, r));
console.log(res);
I use a state variable r.n within the initial array in the reduce operation. You may or may not chose to delete it afterwards.

Categories