Get data from each array of array with sequence output - javascript

i am trying to get sequence index of each array of array like I have an element of the array and that 5 arrays have multiple elements and I want to get the first index of each array then the second and so.
below is my array data
const arrData = [[1,2,4,6],[3,8,7],[12,13],[],[9,10]];
and my expected outout [1,3,12,9,2,8,13,10,4,7,6]
give me some sort of solution to fix my issue

Following might work:
const src = [[1,2,4,6],[3,8,7],[12,13],[],[9,10]],
pickByOne = arr => {
const result = [],
{length} = arr.flat()
while(result.length < length){
for(a of arr){
a.length && result.push(a.shift())
}
}
return result
}
console.log(pickByOne(src))

You can also use zip from lodash. Since the function takes a sequence of arguments and you have an array, you'll need to spread the array with ...
const _ = require("lodash");
const arrData = [[1,2,4,6],[3,8,7],[12,13],[],[9,10]];
const z = _.zip(...arrData)
This will give you the following result:
[
[ 1, 3, 12, undefined, 9 ],
[ 2, 8, 13, undefined, 10 ],
[ 4, 7, undefined, undefined, undefined ],
[ 6, undefined, undefined, undefined, undefined ]
]
You can already see it's in the order that you want. Now to clean things up. You can use flatMap in its simplest form to flatten the array.
// lodash
const fm = _.flatMap(z)
// or with Array.prototype.flat()
const fm = z.flat()
This will give you a single array.
[
1, 3, 12,
undefined, 9, 2,
8, 13, undefined,
10, 4, 7,
undefined, undefined, undefined,
6, undefined, undefined,
undefined, undefined
]
Now you just need to remove all the undefined elements by filtering (keeping) all the elements that are not undefined.
// lodash
_.filter(fm, _.negate(_.isUndefined))
and you have your final result.
[1, 3, 12, 9, 2, 8, 13, 10, 4, 7, 6]
There are many ways to solve this issue so you'll need to decide based on your particular case and balance simplicity, code legibility, efficiency, etc.

Find the longest length of the sub-array using Array.map() to get the length of all sub-arrays, and Math.max(). Use Array.from() to create an array with the length of the longest length. For each index in the created array, use Array.flatMap() to get all items from the original sub-arrays. If the item is undefined, use the Nullish coalescing operator (??) to substitute it with an empty array, which Array.flatMap() would ignore when flattening the resulting array. Flatten the output of Array.from() using Array.flat() to get a single array.
const fn = arr =>
Array.from({ length: Math.max(...arr.map(o => o.length)) }, (_, i) =>
arr.flatMap(o => o[i] ?? [])
).flat();
const arrData = [[1,2,4,6],[3,8,7],[12,13],[],[9,10]];
const result = fn(arrData);
console.log(result);

Please try my below solution may be it will fix your
let data = [[], [], [1, 2, 4, 6], [8, 9, 10], [], [12], [14, 15], []], index = 0;
data = data.filter(o => o.length != 0)
const result = [];
for (i = 0; i < data.length; i++) {
if (data[i].length > index) {
index = data[i].length
}
if (data[i].length > 0) {
for (j = 0; j < index; j++) {
if (data[j][i] != undefined) {
result.push(data[j][i]);
}
}
}
}
console.log("Result", result);

Since it's a nested array, you can loop through and check if the first element of each nested array is undefined or not. If no, you can push it into the result array. I wrote the function for your ref. Please check
const arrData = [[1, 2, 4, 6], [3, 8, 7], [12, 13], [], [9, 10]];
function sorter(arr) {
var result = [];
if (arr.length > 0) {
for (var i = 0; i < arr.length; i++) {
if (arr[i].length > 0) {
if (arr[i][0] !== undefined) {
result.push(arr[i][0]);
}
}
}
}
return result;
}
console.log(sorter(arrData));
I hope this is what you expected! Please reach me if you need clarification.

You need to keep track of the index which defines the position of the elements to get in each iteration.
Use a while loop that would terminate when there are no remaining elements in any of the arrays at a certain index.
Use .map to get a list of elements in each array at the index
Remove undefined elements in this list using .filter in case one of the arrays has no element at an index
Use .isEmpty to check if this list is empty, then, terminate
const arrData = [[1,2,4,6],[3,8,7],[12,13],[],[9,10]];
let res = [], index = 0;
while(true) {
const elementsAtIndex = _.filter(
_.map(arrData, e => e[index]),
e => e!==undefined
);
if(_.isEmpty(elementsAtIndex)) break;
res = [...res, ...elementsAtIndex];
index++;
}
console.log(...res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"></script>

Simple one without any operator whould look like....
const ipArr = [ [1, 2, 4, 6], [8, 9, 10], [], [12], [14, 15], [] ]
let maxLength = 0
for (let i = 0; i < ipArr.length; i++) {
if (ipArr[i].length > maxLength) maxLength = ipArr[i].length
}
const opArr = []
for (let j = 0; j < maxLength; j++) {
for (let k = 0; k < ipArr.length; k++) {
if (ipArr[k][j]) opArr.push(ipArr[k][j])
}
}
console.log('opArr = ', opArr)

Related

Trying to merge two unsorted arrays in Javascript

I have written code in javascript trying to return a single sorted array by giving two sortedarray inputs.
function finalArray(arr1, arr2) {
const mergedArray = [];
if (arr1.length === 0) {
return arr2;
}
if (arr2.length === 0) {
return arr1;
}
let arr1Item = arr1[0];
let arr2Item = arr2[0];
let i = 1;
let j = 1;
while (arr1Item || arr2Item) {
if (arr2Item === undefined || arr1Item < arr2Item) {
mergedArray.push(arr1Item);
arr1Item = arr1[i];
i++;
} else {
mergedArray.push(arr2Item);
arr2Item = arr2[j];
j++;
}
}
return mergedArray
}
console.log(finalArray([2, 6, 4, 10], [15, 1, 5, 33]));
Can anyone help with how to merge unsorted arrays?
Merge your two arrays first, then perform the sort?
const arr1 = [2, 6, 4, 10];
const arr2 = [10, 1, 5, 33];
const newArray = ([...arr1, ...arr2]);
newArray.sort(function(a,b){return a - b});
console.log(newArray);
Expected output: [1, 2, 4, 5, 6, 10, 10, 33]
The problem is you are comparing every two pair of data and pushing smaller one.
First try to sort each sub array without entering compare process for mixing.
After the sub arrays are being sorted, then compare to each other.

Javascript: Split an array according to a pattern: items 1, 5, 10, then 2, 6, 11, then 3, 7, 12

I am trying to split an array which has a repeating pattern of elements 1, 2, 3, and 4. I want to turn my array [1,2,3,4,5,6,7,8,9,10] into four arrays: [1,5,10], [2,6,11], [3,7,12], and [4,8,13]. I tried using multiples, but the result creates the new arrays in a wrong order. Here is my attempt:
var upload_names_and_ids = [
"Certificat de salaire", //first line is the upload's visible title
"certificat-de-salaire", //second line is the upload's id
"no-info-circle", //third line is the info-circle class
"", //fourth line is the info-circle text
"Allocations Familiales",
"alloc-familiales",
"no-info-circle",
"",
"Courrier Impot (déclaration précédente)",
"courrier-impot",
"info-circle right",
""
];
//Seperate our first array into 4
var upload_names = [];
var upload_ids = [];
var upload_info_circle_class = [];
var upload_info_circle_content = [];
for (var i=0; i<upload_names_and_ids.length; i++){
if (i%4==0) {
upload_info_circle_content.push(upload_names_and_ids[i]);
} else if (i%3==0) {
upload_info_circle_class.push(upload_names_and_ids[i]);
} else if (i%2==0) {
upload_names.push(upload_names_and_ids[i]);
} else {
upload_ids.push(upload_names_and_ids[i]);
}
}
Any help is much appreciated, thank you!
You could take a remainder with index and wanted length.
const
array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
length = 4,
result = array.reduce(
(r, v, i) => (r[i % length].push(v), r),
Array.from({ length }, _ => [])
);
console.log(result);
If you like to use predeclared array directly, you could replace this line
Array.from({ length }, _ => [])
with
[upload_names, upload_ids, upload_info_circle_class, upload_info_circle_content]
where the accumulator of Array#reduce keeps the object references.
It's not i%3==0 (which matches 0, 3, 6, …) but i%4==1 (to match 1, 5, 10, …). Same for i%2==0.
I would add a helper sliceN that takes an array and a positive integer. Then returns an array of arrays where the inner arrays are of length n.
sliceN([1,2,3,4,5,6,7,8,9], 3) //=> [[1,2,3], [4,5,6], [7,8,9]]
sliceN([1,2,3,4,5,6], 2) //=> [[1,2], [3,4], [5,6]]
Then also add a helper transpose that transposes a matrix.
transpose([[1,2,3], [4,5,6], [7,8,9]]) //=> [[1,4,7], [2,5,8], [3,6,9]]
transpose([[1,2], [3,4], [5,6]]) //=> [[1,3,5], [2,4,6]]
With these two helpers you can create the wanted result with ease.
const upload_names_and_ids = [
"Certificat de salaire", //first line is the upload's visible title
"certificat-de-salaire", //second line is the upload's id
"no-info-circle", //third line is the info-circle class
"", //fourth line is the info-circle text
"Allocations Familiales",
"alloc-familiales",
"no-info-circle",
"",
"Courrier Impot (déclaration précédente)",
"courrier-impot",
"info-circle right",
""
];
const [
upload_names,
upload_ids,
upload_info_circle_class,
upload_info_circle_content,
] = transpose(sliceN(upload_names_and_ids, 4));
console.log(upload_names);
console.log(upload_ids);
console.log(upload_info_circle_class);
console.log(upload_info_circle_content);
function sliceN(array, n) {
const slices = [];
for (let i = 0; i < array.length; i += n) {
slices.push(array.slice(i, i + n));
}
return slices;
}
function transpose(rows) {
if (rows.length == 0) return [];
const columns = rows[0].map(cell => Array.of(cell));
for (let iRow = 1; iRow < rows.length; iRow += 1) {
for (let iCol = 0; iCol < columns.length; iCol += 1) {
columns[iCol].push(rows[iRow][iCol]);
}
}
return columns;
}
If you are already use a library with helper functions chances are that one or both of these data transforming methods are present. sliceN can often be found as something with split, slice or chunk in the name. transpose is very specific and if present will probably be present under the same name.
As an example Ramda offers both these methods.
R.transpose(R.splitEvery(4, upload_names_and_ids))

JavaScript: Add sum of even value elements to each odd value element in an given array; show the new array

I need to write a code that adds the sum of even value elements to each odd value element in a given array and then show the new array.
Example:
array = [2,3,4,5,6,7,8,9]
Requested sum is 20. The new generated array should look like:
array = [2, 23, 4, 25, 27, 8, 29]
What I have done so far:
let oldArray = [2, 3, 4, 5, 6, 7, 8, 9];
const sumArray = arr => arr.filter(i => !(i % 2)).reduce((a, b) => a + b);
let newArray = oldArray.map (i => i%2 == 1 + sumArray);
console.log(newArray);
Take a look at this:
let array = [2, 3, 4, 5, 6, 7, 8, 9];
console.log(array.map(x=>x%2==0?x:x+array.reduce((a,b)=> a + b*((b+1)%2) )))
It's logging an array built on the original array: if the element is even, you leave it that way. If not, you add the sum of the even numbers. How do you do this? You add the element multiplied by the rest of the division of this element added to 1 by 2.
let array = [2,3,4,5,6,7,8,9];
let newarray = [];
let sum = 0;
for(let i=0; i<array.length; i++) {
if(array[i]%2 === 0) {
sum += array[i];
}
}
for(let i=0; i<array.length; i++) {
if(array[i]%2 === 0) {
newarray.push(array[i]);
}
else {
newarray.push(array[i]+sum);
}
}

How can I store numbers in arrays?

I built a program that check if there are two common numbers in two different arrays, and then log those numbers. I was able to do that using a simple for loop that goes trough each element of the first array and check if there is an equal element in the second array. Each of the same element in the arrays are stored in a third array called "commonNumbers" which I logged at the end of the program.
const firstNumbers = [12, 45, 6, 78]
const secondNumbers = [6, 7, 12, 45]
let commonNumbers = []
for (let i = 0; i < firstNumbers.length; i++) {
for (let j = 0; j < secondNumbers.length; j++) {
if (firstNumbers[i] === secondNumbers[j]) {
commonNumbers += secondNumbers[j]
}
} }
console.log(commonNumbers)
The result for this example is the seguent:
12456
[Finished in 0.2s]
My question is about the result. I can see that the program actually worked and logged the same element in the arrays (12, 45, 6), but I can't figure out why "commonNumbers" stored the result in such a way that there are no spaces between the numbers.
I would like to clearly see each number.
For example if I call the first element of "commonNumbers" (of index 0):
commonNumbers[0] the result I will get is not going to be "12" as expected, but "1".
Same thing happen if I say: commonNumbers[2] the result is going to be "4", not "6".
Apparently "commonNumbers" array stored the element in a different way I was expecting. How can I solve this, using this "storing" method?
This is because +=, on your array, implicitly convert it to a string, as you can see in the example below, where a Number is summed to an Array.
console.log(typeof([] + 1));
Just use the comfortable .push (read more about push here) method of arrays in order to add the element:
const firstNumbers = [12, 45, 6, 78]
const secondNumbers = [6, 7, 12, 45]
let commonNumbers = []
for (let i = 0; i < firstNumbers.length; i++) {
for (let j = 0; j < secondNumbers.length; j++) {
if (firstNumbers[i] === secondNumbers[j]) {
commonNumbers.push(secondNumbers[j]);
}
} }
console.log(commonNumbers)
As a (final) side note, there are several other ways to accomplish your task, the cleverest you can probably go with is filter. You may also would take care of eventual duplicates, since if your input array has two identical numbers the commonsNumber result will contain both, which might be unintended.
The "definitive" clever solution that tries to also take care of duplicates and to loop the shorter array would be something like this:
// Inputs with duplicates, and longer array on second case.
const firstNumbers = [12, 45, 6, 78, 12, 12, 6, 45];
const secondNumbers = [6, 7, 12, 45, 45, 45, 12, 6, 99, 19, 5912, 9419, 1, 4, 8, 6, 52, 45];
// Performance: look for duplicates starting from the shortest array. Also, make a set to remove duplicate items.
const [shortestArray, longestArray] = firstNumbers.length < secondNumbers.length ? [firstNumbers, secondNumbers] : [secondNumbers, firstNumbers];
// Remove duplicates.
const dedupes = [...new Set(shortestArray)];
// Find commomn items using filter.
const commons = dedupes.filter(i => longestArray.indexOf(i) > -1);
console.log('commons is', commons);
Don't get me wrong, the solution is fine, just wanted to add "something" to the boilerplate, to take care of eventual additional scenarios.
const firstNumbers = [12, 45, 6, 78]
const secondNumbers = [6, 7, 12, 45]
let commonNumbers = []
for (let i = 0; i < firstNumbers.length; i++) {
for (let j = 0; j < secondNumbers.length; j++) {
if (firstNumbers[i] === secondNumbers[j]) {
commonNumbers.push(secondNumbers[j])
}
} }
The push method appends values to an array.
You seem to be looking for array.prototype.push (mdn). E.g.:
const firstNumbers = [12, 45, 6, 78]
const secondNumbers = [6, 7, 12, 45]
let commonNumbers = []
for (let i = 0; i < firstNumbers.length; i++)
for (let j = 0; j < secondNumbers.length; j++)
if (firstNumbers[i] === secondNumbers[j])
commonNumbers.push(secondNumbers[j]);
console.log(commonNumbers); // as an array
console.log(commonNumbers.join(', '));
why "commonNumbers" stored the result in such a way that there are no spaces between the numbers.
The + operator will try to cast its operands to compatible types. In this case, that is a string, where empty arrays [] are cast to empty strings '', and numbers 3 are cast to the corresponding string '3'. E.g. [] + 3 is the string '3'.
console.log([], typeof []);
console.log(3, typeof 3);
console.log([] + 3, typeof ([] + 3));

How to limit for 10 results the array.filter?

I have big array, I want to make an autocomplete search, but I want to display only 10 results, so stop iterating through the array by the time there were found 10 results. I have made this:
let items = array.filter(r => r.indexOf(term)!=-1);
console.log(items.length) // lots of items, need to be limited to 10
It works but I don't know how to stop the array.filter by the time it reaches the desired limit.
You could use another variable to keep track of how many items matched the condition so far and always return false after the limit has been reached. Here is an example:
const arr = [1,0,2,0,3,0,4,5,6,7,8,9,10,11,12,13,14];
const filtered = arr.filter(function(item) {
if (this.count < 10 && item > 0) {
this.count++;
return true;
}
return false;
}, {count: 0});
console.log(filtered);
Here, I'm using an object {count: 0} as the context of the callback function. You can find out more about Array.filter from here
Basically you can use a generator function, which can be stopped by a self made limit, like in the below function
function *filter(array, condition, maxSize) {
if (!maxSize || maxSize > array.length) {
maxSize = array.length;
}
let count = 0;
let i = 0;
while ( count< maxSize && i < array.length ) {
if (condition(array[i])) {
yield array[i];
count++;
}
i++;
}
}
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log( Array.from( filter(array, i => i % 2 === 0, 2 ) ) ); // expect 2 & 4
So it will stop after it reaches maxSize as a parameter, and to easily return it into an array, you can use Array.from, which will iterate the iterator of the generator function
You could hand over a counter and omit any other values for filtering.
const
filter = v => v % 2,
filterMax = (fn, c) => x => c && fn(x) && c--,
max = 3,
array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
result = array.filter(filterMax(filter, max));
console.log(result);
Taking the idea of Icepickle's answer a bit ahead with a loop for finding the next valid item and yield this one.
function* filterMax(array, cb, count) {
var i = 0;
while (count) {
while (i < array.length && !cb(array[i])) i++;
if (i >= array.length) return;
yield array[i++];
count--;
}
}
const
filter = v => v % 2,
max = 3,
array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
console.log(...filterMax(array, filter, max));
You can't break from Array.prototype.filter method. It will loop over every element. You can use a simple for loop and break when 10 items are found
const items = []
for (const value of array) {
if (value.includes(term))
items.push(value)
if (items.length === 10)
break;
}
Just for the trick :
EDIT : To clarify this code will pick the 10 first even number of the list
let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30];
const result = array.reduce((temp, value) => {
if(value%2==0 && temp.length<10)
temp.push(value);
return temp;
}, []);
console.log(result);
var data = ["1","2","3","4","5","6","7","8","9","10","11","12","13","14"]
var limited = data.filter((val,i)=>i<10)
console.log(limited)
You can do this just simple add .Slice(0,NO_OF_ELE_WANT)
eg. finding first two even no
[1,2,3,4,5,6,7,8,9,10].filter((e)=> e%2==0).slice(0,2)
Answer : let items = array.filter(r => r.indexOf(term)!=-1).slice(0,10);
I wrote a library that's handy for this sort of thing.
Here's how I'd find the first 100 numbers that start with the character "1"
const {blinq, range} = window.blinq;
//create a large array of strings to search
const arrToBeSearched = range(0,10000)
.select(x => `${x}`)
.toArray()
const query = blinq(arrToBeSearched)
.where(x => x.startsWith("1"))
.takeWhile((x, i) => i < 100)
const result = [...query] //no calculation until we materialize on this line
console.log(result)
<script src="https://cdn.jsdelivr.net/npm/blinq"></script>
I know its a bit late, but here's for the new comers!
// we'll create a function which will take two arguments
// first argument would be your original array which your want to filter from
// second argument would be the number of results you want the filter to return
const limitedArray = (originalArray, limit) => {
let newArray = [];
for (let item of originalArray) {
if (newArray.length >= limit) break;
//your code here
//in my case i'll jush push in to the array
newArray.push(item)
}
return newArray;
};
//---------------->ignore v<-------------------
//the above function would return an array so in other words we can see this function as an array
const array = [1, 2, 3, 4, 5, 6, 'cascas', 'ascasc', 9, 10, 'ascs'];
console.log(limitedArray(array, 4));
//similarly
limitedArray(array, 4).forEach(item => {
console.log(item)
})
You can define your custom method on Array.prototype which will take 2 arguments. A callback and a max elements that result array will contain.
The code below gets the first 3 odd numbers from array.
function filterUpto(callback,max){
let len = this.length
let res = [];
let i = 0;
while(res.length < max && i < len){
if(callback(this[i],i,this)) res.push(arr[i])
i++
}
return res;
}
Object.defineProperty(Array.prototype,'filterUpto',{
value:filterUpto
})
let arr = [1,2,3,4,5,6,7,8,9,10];
console.log(arr.filterUpto(x => x % 2,3)); //first three odd numbers
Here is another possible solution, pretty straightforward, using Array.from:
const arr = [
"foo",
"bar",
"foobar",
"baz",
"foobaz",
"artefact",
"mortar",
"bar",
"arity",
"mark",
"car",
"dare",
"arbitrary",
"tar",
"jar",
"war",
];
const filterWithLimit = (arr, value, length) =>
Array.from(
{ length },
function () {
return arr
.slice(this.index++)
.find((option, i) => (this.index += i, option.includes(value)));
},
{ index: 0 }
);
console.log(filterWithLimit(arr, "ar", 10));
Here is a short solution which doesn't continue searching after the limit is reached:
function filter_n(array, limit, test) {
let ret = []
array.find((x)=> test(x) && ret.push(x)>=limit )
return ret
}
when test(x) is true, it calls ret.push(x) (which adds x to ret and outputs the length of ret)
then, once ret's length is >= limit, the inner function returns true, and find stops looping because it "found" a result

Categories

Resources