Using join method dynamically - javascript

I have a reference array based on each English alphabet index:
let reference = [0, 2, 3];
and an array of words or even phrases:
let words = ["A", "C", "D"];
And I want to join each word from words array to create a simple sentence but considering the gaps between words ( whenever the values in the reference array aren't consecutive numbers! ), so the desired output would be :
A...C D // gaps filled with three dots
The problem is I can't find a solution to use join() method to do it!
Any help would be appreciated

You can create a new array from words based on the gaps in reference and then join:
let reference = [0, 2, 3];
let words = ["A", "C", "D"];
let res = [];
reference.forEach((n, i) => {
if (n - reference[i - 1] >= 2) res.push('...', words[i]);
else res.push(words[i]);
});
console.log(res.join(' '));

You could reduce the array by checking the delta of the last value and the actual value.
var reference = [0, 2, 3],
result = reference.reduce((r, v, i, { [i - 1]: last }) =>
r + (r && (i && v - last > 1 ? '...' : ' ')) + (v + 10).toString(36).toUpperCase(), '');
console.log(result);

An approach of comparing reference array values each time while iterating on the actual words array:
let reference = [0, 2, 3, 4, 7];
let words = ["A", "C", "D", "E", "H"];
let prev = 0;
let joined = words[prev];
for (let i = 1, l = words.length; i < l; ++i) {
const diff = reference[i] - reference[prev];
if (diff > 1) {
joined += "..." + words[i];
} else {
joined += " " + words[i];
}
prev = i;
}
//Since CDE ar continuous and AC and EH are not
console.info(joined);

Related

jquery split array with last element of a chunk being first element of the next chunk

I want to split an array in jquery so that after splitting, the last element for previous array should be the first element of current array.
var arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
If I do splice then it will splice exactly same size and next array will be next element. so if I am splicing it into 5 my output should be
var firstArr = arr.splice[0,4];
var secondArr = arr.splice[0,4];
var thirdArr = arr.splice[0,4];
var fourthArr = arr.splice[0,4];
var fifthArr = arr.splice[0,4];
Right now I am getting
[1,2,3,4]
[5,6,7,8]
...
What I need is
//firstArr = [1,2,3,4];
//secondArr = [4,5,6,7];
//thirdArr = [7,8,9,10];
//fourthArr = [10,11,12,13];
//fifthArr = [13,14,15,16];
How to achieve this in jQuery ?
I don't know a jquery array function that is preferable to using a plain javascript solution. Below is an example that generically handles your requirement by:
taking the number of chunks as the ceil of: the length of input array plus the floor number of duplicated entries, all divided by the size of the output chunk
uses slice such that the last element for previous array is the first element of current array.
// chunking function
function chunk(arr, size) {
if (size === 0) return [];
var arrCount = Math.ceil((arr.length + Math.floor(arr.length / size)) / size);
var chunks = [];
for (let i=0; i<arrCount; ++i) {
chunks.push(arr.slice(i * (size - 1), i * (size - 1) + size));
}
return chunks;
}
// tests
console.log(chunk([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16], 4));
console.log(chunk([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16], 7));
console.log(chunk([1,2,3,4,5,6,7,8,9], 3));
console.log(chunk([1,2,3,4,5,6,7,8,9,10], 3));
console.log(chunk([1,2,3], 8));
console.log(chunk([], 10));
console.log(chunk([1, 2, 3, 4], 0));
console.log(chunk(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'], 4));
.as-console-wrapper { max-height: 100% !important; top: 0; }
const arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
let slices = []
let start = 0
let end = 3
for(i = 0; i < 5; i++){
let slice = arr.slice(start,end)
slice.push(arr[end])
start += 3
end += 3
slices.push(slice)
}

how to add 3 different number to the i, i+1 and i+2 of my array

I want to know how can I add 3 different number to the 3n, 3n+1 and 3n+2 indices. I mean for example I have following array :
var arr = [1,1,1,2,2,2,3,3,3]
and then I want add the (3n)th to 5 and then I want add (3n+1)th of an array to 2 and (3n+2) to 3,
I mean the final array I want to be like following result array:
var result = [6,3,4,7,4,5,8,5,6]
and I try to do it as following code:
// arr = [1,1,1,2,2,2,3,3,3]
let res = [];
for (let i = 0; i < arr.length; i++) {
res.push([arr[i*3] * 5,
arr[(i*3)+1] *2,
arr[(i*3)+2] *3])
}
This should do the trick:
var arr = [1,1,1,2,2,2,3,3,3],
add = [5,2,3], res=[];
// result = [6,3,4,7,4,5,8,5,6]
for (let i=0;i<arr.length;i+=add.length) add.forEach((v,j)=>res[i+j]=arr[i+j]+v);
console.log(JSON.stringify(res))
An alternative and even shorter solution (similar to #Robin's answer) would be:
var arr = [1,1,1,2,2,2,3,3,3],
add = [5,2,3], res=[];
res=arr.map((v,i)=>v+add[i%add.length]);
console.log(JSON.stringify(res))
( I noticed #Nina came up with a very similar answer ...)
You can simply use map, making use of the fact that its function argument takes the current index an optional second argument:
var arr = [1,1,1,2,2,2,3,3,3];
var result = arr.map((num, idx) => {
switch (idx % 3) {
case 0:
return num + 5;
case 1:
return num + 2;
case 2:
return num + 3;
}
});
console.log(result);
You could mapp the array directly by taking a closure over an index for the values array for adding.
var array = [1, 1, 1, 2, 2, 2, 3, 3, 3],
add = [5, 2, 3],
result = array.map((i => v => v + add[i++ % add.length])(0));
console.log(...result);

Substitute random items in a Javascript array

In Javascript, am trying to randomly substitute half (in this case, 3 out of 6) of the items from an array with different ones (all of the same type), and I need the original items' position to be kept. So for instance, if I have:
var my_array = [a, b, c, d, e, f]
I would want to select three random ones to be substituted with a 0, while the others to keep their initial position. So let's say a, c, and d are the ones the random selector will make go away on one instance, then my array would become:
my_array = [0, b, 0, 0, e, f]
On a different run, the random selector would perhaps pick b, c, and f and so I'd have:
my_array = [a, 0, 0, d, e, 0]
And so on.
Thank you so much for your help!
You could take a closure over the array and wanted zero counts and return a function which generates random integer and map the array with zeros or values.
function getRandom(array, count) {
return function () {
const indices = new Set();
do {
indices.add(Math.floor(Math.random() * array.length));
} while (indices.size < count)
return array.map((v, i) => indices.has(i) ? 0 : v);
};
}
var myArray = ['a', 'b', 'c', 'd', 'e', 'f'],
getArrayWithZeros = getRandom(myArray, 3);
console.log(...getArrayWithZeros());
console.log(...getArrayWithZeros());
console.log(...getArrayWithZeros());
console.log(...getArrayWithZeros());
console.log(...getArrayWithZeros());
Another option
const myArray = ['a', 'b', 'c', 'd', 'e', 'f'];
// Randomizer function
const rand = ([...arr], len, rep) => {
let ins = {};
while(Object.keys(ins).length < len) {
let r = ~~(Math.random() * arr.length);
if(!ins[r]) ins[r] = true;
}
for(let i = 0; i < arr.length; i++) if(ins[i]) arr[i] = rep;
return arr;
}
// Array, number of elements to replace, replace with
// Here we transform toString for better readability
console.log(rand(myArray, 3, 0).toString());
console.log(rand(myArray, 3, 0).toString());
console.log(rand(myArray, 3, 0).toString());
console.log(rand(myArray, 3, 0).toString());
console.log(rand(myArray, 3, 0).toString());
You need to calculate half of the length of the array, generate random indexes of this amount, and then change them:
var my_array = ['a', 'b', 'c', 'd', 'e', 'f'];
function alterHalfWithZero(arr){
let my_array = [...arr];
let indexList = {};
let len = Math.floor(my_array.length / 2)
while(Object.values(indexList).length != len){
let random_index = Math.floor(Math.random() * my_array.length);
indexList[random_index] = random_index;
}
indexList = Object.values(indexList);
for(let i = 0; i < indexList.length; i++)
my_array[indexList[i]] = 0;
return my_array;
}
console.log(...alterHalfWithZero(my_array));
console.log(...alterHalfWithZero(my_array));
console.log(...alterHalfWithZero(my_array));
First get unique random indexes.
Loop over the indexes and make them 0.
var my_array = ["a", "b", "c", "d", "e", "f"];
// Get unique random indexes
const random = (num, count) => {
const set = new Set();
while (set.size < count) {
set.add(Math.floor(Math.random() * num));
}
return [...set];
};
const alter = (arr, count = 3) => {
const output = [...arr];
random(arr.length, count).forEach((index) => (output[index] = 0));
return output;
};
console.log(alter(my_array));
console.log(alter(my_array));
Here is one solution.
var my_array = ["a", "b", "c", "d", "e", "f"];
const substitute = array => {
const indexes = Array.from(Array(array.length).keys())
.sort(() => Math.random() - 0.5)
.slice(0, array.length / 2);
return array.map((value, index) =>
indexes.some(i => i === index) ? value : 0
);
};
console.log(substitute(my_array));

Efficiently merge two arrays by distribute values evenly

I have seen many question/answer subject to merge two array by alternating Values. they are working like this:
let array1 = ["a", "b", "c", "d"];
let array2 = [1, 2];
let outcome = ["a",1 ,"b", 2, "c", "d"]
but i want output to be more efficient with even distribution of value based on array size.
expected outcome = ["a","b", 1, "c", "d", 2]
other scenario
let array2 = [1];
expected outcome = ["a","b", 1, "c", "d"]
what should be the best way to achieve this sort of merging?
Find the ratio of the two arrays' lengths, longest.length/shortest.length and then take that many from the longest for every one in the shortest.
let array1 = ["a", "b", "c", "d", "e"];
let array2 = [1, 2];
const evenDistribute = (array1, array2) => {
const longest = array1.length > array2.length ? array1 : array2;
const shortest = array1.length > array2.length ? array2 : array1;
const ratio = Math.floor(longest.length / shortest.length);
const results = [];
for (let i = 0; i < shortest.length; i++) {
for (let j = 0; j < ratio; j++) {
results.push(longest[i * ratio + j]);
}
results.push(shortest[i]);
}
// Grab any that are left over
for (let i = longest.length - (longest.length % shortest.length); i < longest.length; i++) {
results.push(longest[i]);
}
return results;
}
console.log(evenDistribute(array1, array2));
The idea is to find out per how many items of the long array you will have to mix an item from the short array. The code below is to demonstrate the concept. Maybe you will have to adjust it a little bit for all edge scenarios.
let array1 = ["a", "b", "c", "d"];
let array2 = [1, 2];
//Get the long and short arrays and calc the length factor
var [longArray, shortArray] = array1.length >= array2.length ? [array1, array2] : [array2, array1];
let lengthFactor = longArray.length / shortArray.length;
var c = 0
let smallIdx = 0;
let result = longArray.flatMap(item => {
c++;
if (c % lengthFactor === 0) {
return [item, shortArray[smallIdx++]]
}
else
return [item];
})
console.log(result);
You could get the interval for distribution. Then loop through the second array and use splice to update the specific indices of the first array.
function distribute(original, replace) {
const interval = Math.ceil(original.length / (replace.length + 1));
replace.forEach((r, i) => original.splice(interval * (i + 1) + i, 0, r))
console.log(...original)
}
distribute(["a", "b", "c", "d"], [1])
distribute(["a", "b", "c", "d"], [1, 2])
distribute(["a", "b", "c", "d"], [1, 2, 3])
distribute(["a", "b", "c", "d", "e", "f"], [1, 2])
distribute(["a", "b", "c", "d", "e", "f"], [1, 2, 3])
This function was influenced by adiga's answer but handles the distribution a little better by calculating the insert index based on a decimal interval instead of Math.ceil.
It also avoids mutating the input arrays by creating a copy of the long array before inserting the short array's data.
If you find any cases that it doesn't cover let me know :)
function mergeAndDistributeArrays(array1, array2) {
// Find the long/short arrays based on length
const [long, short] =
array1.length >= array2.length ? [array1, array2] : [array2, array1];
// Calculate the interval
const interval = long.length / (short.length + 1);
// Copy the long array so we don't mutate the input arrays
const merged = [...long];
// Iterate the short array and insert the values into the long array
short.forEach((value, index) => {
// Calculate the insert index based on the interval and the current index
const insertAt = Math.ceil(interval * (index + 1));
// Insert the value
merged.splice(insertAt + index, 0, value);
});
return merged;
}
console.log(
mergeAndDistributeArrays(
[1,2,3],
['a','b','c','d','e','f','g','h','i']
)
);
let array1 = ['a', 'b', 'c', 'd', 'e'];
let array2 = [1, 2];
function merge(arr1, arr2) {
let newArr1 = JSON.parse(JSON.stringify(arr1));
let newArr2 = JSON.parse(JSON.stringify(arr2));
[newArr1, newArr2] = newArr1.length >= newArr2.length ? [newArr1, newArr2] : [newArr2, newArr1];
const interval = newArr1.length / newArr2.length;
newArr2.map((item, index) => {
newArr1.splice(interval * (index + 1), 0, item);
})
return newArr1;
}
console.log(merge(array1, array2));
const mix = (firstArray, secondArray) => {
const itrArray = firstArray.length > secondArray.length ? firstArray : secondArray;
const result = [];
for(let i=0; i<itrArray.length; i++){
firstArray[i] && result.push(firstArray[i]);
secondArray[i] && result.push(secondArray[i]);
}
return result;
}
console.log(mix([1, 2, 3], [4, 5, 6]));
// [1, 4, 2, 5, 3, 6]
console.log(mix(["h", "a", "c"], [7, 4, 17, 10, 48]));
// ["h", 7, "a", 4, "c", 17, 10, 48]

Get small element index till array length

I have to sort an array and want to get index so that I can sort another array on the basis of this index..
There are two array a and b I saved division of that array in third array that is sortDiv now I want index of small element so that I can sort a and b according to index..
Code is like
var a = [6, 7, 8, 9];
var b = [1, 2, 3, 4];
var sortA = [],
sortB = [],
sortDiv = [];
var div = a[0] / b[0];
for (var i = 0; i < a.length; i++) {
sortDiv.push(a[i] / b[i]);
}
var temp = sortDiv;
for (var i = 1; i < sortDiv.length; i++) {
var val = Math.min.apply(Math, temp);
var key = sortDiv.indexOf(val);
sortA.push(a[key]);
sortB.push(b[key]);
if (key > -1)
temp.splice(key, 1);
}
console.log(sortA + " " + sortB);
I got [9,8] for a and [4,3] for b..while I want a=[9,8,7,6] b=[1,2,3,4]
But splice is not a good option..I need a function that remove only element not an index..any idea please?
UPDATED
As problem is solved but I want to know that
Is it possible to remove element but not an index in array?
Try not removing element just replacing it with maximum element +1 and it will work fine here is the updated code
var a = [6, 7, 8, 9];
var b = [1, 2, 3, 4];
var sortA = [],
sortB = [],
sortDiv = [];
var div = a[0] / b[0];
for (var i = 0; i < a.length; i++) {
sortDiv.push(a[i] / b[i]);
}
console.log(sortDiv);
var temp = sortDiv;
var max = Math.max.apply(Math, temp); // here we find the maximum
max += 1;
for (var i = 1; i <= sortDiv.length; i++) {
var val = Math.min.apply(Math, temp);
console.log(val);
var key = sortDiv.indexOf(val);
sortA.push(a[key]);
sortB.push(b[key]);
temp[key] = max; // here we update the minimum with maximum+1
}
console.log(sortA + " " + sortB);
If the question is about using splice to remove an item based on the value and not the index, get the index, then use splice:
var a = ['a', 'b', 'c'];
a.splice(a.indexOf('b'), 1);
console.log(a); // ["a", "c"]

Categories