Related
I want to filter a large array list into multiple arrays for every 5 items in a certain way so that [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] would be [[1, 2, [3, 4, 5]], [6, 7, [8, 9, 10]]] or [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] would be [[1, 2, [3, 4, 5]], [6, 7, [8, 9, 10]], [11, 12, [13, 14, 15]]]. (All arrays will be a multiple of 5 in my program.)
How would I do this?
Right now I'm doing this
for (var i = 1; i < (stoneTextureUnfiltered.length+1)/1.01; i++) {
stoneTexture.push([stoneTextureUnfiltered[i], stoneTextureUnfiltered[i+1], stoneTextureUnfiltered[i+2], [stoneTextureUnfiltered[i+3], stoneTextureUnfiltered[i+4], stoneTextureUnfiltered[i+5]]]);
}
but it doesn't seem to be working.
Thanks,
-Voxel
Assuming you've chunked the array already into parts of 5 with these answers and it's stored in a variable named chunks, to wrap the last 3 in each chunk you can use map:
const final = chunks.map((chunk) => [chunk[0], chunk[1], chunk.slice(2)]);
You add the first and second elements to the new list, then add the rest of the chunk as a whole.
Demo below:
// using second answer
var perChunk = 5 // items per chunk
var inputArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
var chunks = inputArray.reduce((resultArray, item, index) => {
const chunkIndex = Math.floor(index/perChunk)
if(!resultArray[chunkIndex]) {
resultArray[chunkIndex] = [] // start a new chunk
}
resultArray[chunkIndex].push(item)
return resultArray
}, [])
// answer below
const final = chunks.map((chunk) => [chunk[0], chunk[1], chunk.slice(2)]);
console.log(final);
As you can see, it works nicely!
what's up? I hope you going well.
So, my question is, I have a array with number that I have to compare with another arrays (like 1 to X), what is the best way to:
1º compare the arrays and retrieve the numbers that are equals.
2º the numbers of elements that are equal (without using .length on the array with numbers are equals).
Example:
Array 1 = [1, 3, 4, 5, 6, 7, 8, 9, 11, 13, 16]
Array 2 = [1, 2, 3, 7, 9, 12, 16, 17]
That way, the total numbers is 5
And the numbers are: [1, 3, 7, 9, 16]
My method is using forEach and compare each item and using .length on the array with the numbers that are equals, there's another way or best way to do this?
Another example using more arrays:
Arr1 = [1, 2, 3, 5, 6, 7, 8, 10, 15]
Arr2 = [
[1, 3, 5, 7, 8, 9, 10, 11, 12],
[2, 5, 6, 7, 9, 10],
[1, 3, 5, 7, 10, 11, 13, 14, 15]
]
// Output
6, [1, 3, 5, 7, 8, 10]
5, [2, 5, 6, 7, 10]
7, [1, 3, 5, 6, 7, 10, 15]
Thanks for the answer.
I like using Set for this purpose. You can create a Set from your first array and then any lookup in that Set (using Set.has) is O(1) efficiency.
const arr1 = [1, 3, 4, 5, 6, 7, 8, 9, 11, 13, 16];
const arr2 = [1, 2, 3, 7, 9, 12, 16, 17];
const arr1Items = new Set(arr1);
const matched = arr2.filter(el => arr1Items.has(el));
console.log(matched.length, matched);
Arr2 is an array, not an object, your code would change accordingly
Arr1 = [1, 2, 3, 5, 6, 7, 8, 10, 15]
Arr2 = [
[1, 3, 5, 7, 8, 9, 10, 11, 12,],
[2, 5, 6, 7, 9, 10],
[1, 3, 5, 7, 10, 11, 13, 14, 15,]
]
Given that, the solution is a oneliner:
res = Arr2.map(a=>a.filter(x=>Arr1.indexOf(x)!=-1).length)
It should be straightforward but, just in case:
The [].indexOf(el) method give you the position of the parameter in the array, if that element is not present it will return -1. Therefore, the function
x => Arr1.indexOf(x)!=-1
returns true or false if x is present or not in the Arr1 array
The [].filter(fn) method use the fn function to evaluate every array element and give as result an array with the evaluated true elements.
a.filter(x => Arr1.indexOf(x)!=-1)
Means give me all the elements of array a presents in Arr1
Now we just have to count the lenght of that array
a.filter(x => Arr1.indexOf(x)!=-1).length
and pass this count to the [].map(fn) method to have the result we need.
The function I wrote below will give the results you want, but remember the function returns an array of arrays, even if the second parameter had only one array or was an array of elements instead of array of arrays (Works for both).
Arr1 = [1, 2, 3, 5, 6, 7, 8, 10, 15]
Arr2 = [
[1, 3, 5, 7, 8, 9, 10, 11, 12],
[2, 5, 6, 7, 9, 10],
[1, 3, 5, 7, 10, 11, 13, 14, 15]
]
Arr3 = [1, 5, 6, 9, 12, 15, 17]
function check(base_array,search_values)
{
if(base_array.length===0 || search_values.length===0)
{
return [];
}
else if(Array.isArray(search_values[0]))// Check if second parameter is an array of arrays.
{
var result=[];
search_values.forEach(search=>{
var result_sub=[];
search.forEach(key=>{
if(base_array.includes(key))
{
result_sub.push(key);
}
});
result.push(result_sub);
});
return result;
}
else
{
var result=[];
search_values.forEach(key=>{
if(base_array.includes(key))
{
result.push(key);
}
});
return [result];
}
}
console.log("Array of Arrays");
console.log(check(Arr1,Arr2));
console.log("Array of Elements");
console.log(check(Arr1,Arr3));
From the returned result you can loop through the value to get the elements and the number of elements by checking length of array.
result.forEach(element=>{
console.log(result.length, result);// number of elements doesn't have to be passed
});
What the Function does is it checks if any array is empty , then returns empty array [], if the second array is an array of arrays it loops through each array and then to each element in the sub array and checks if it exists in the first array, else if the array was array of elements, then it just loops through the elements and checks if it exists in the first array. And returns the result stored
I have an array of unsorted number and another array of sorted number, like
const unSortedArray = [54, 23, 55, 76, 9, 11];
const sortedArray= [1, 2, 3, 4, ...., 100]
How could I find out the first element appears in my sortedArray which should also be an element existed in my unSortedArray? In above example, should return 9 because 9 existed in unSortedArray as well as it positioned prior to other element in sortedArray
Note, I used 1, 2, 3, 4 in my above example, but my real world example was not number but is GUID, let's say we cannot apply sort method on unSortedArray then pick the first element.
I have thought about union both arrays, but how to union both while not break the sorting in sortedArray?
Here is some example
1) output should be 1, because even element 1, 2, 9 and 10 exists in both array, 1 has prior order than 2, 9, 10 in sortedArray
const unSortedArray = [54, 23, 55, 76, 9, 10, 2, 1];
const sortedArray= [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
2) output should be 9, because even element 9 and 10 exists in both array, 9 has prior order than 10 in sortedArray
const unSortedArray = [54, 23, 55, 76, 10, 9];
const sortedArray= [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
3) output should be '' because no element in unSortedArray appears in sorted Array
const unSortedArray = [54, 23, 55, 76, 11];
const sortedArray= [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
A quick and dirty way to do it with a for loop:
const unSortedArray = [54, 23, 55, 76, 9, 11];
const sortedArray= [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let firstVal;
for (i = 0; i < sortedArray.length; i++) {
if (unSortedArray.includes(sortedArray[i])) {
firstVal = sortedArray[i];
break;
}
}
console.log(firstVal);
You can create a Set from the unSortedArray and use set.has() in your predicate for sortedArray.find():
const unSortedArray = [54, 23, 55, 76, 9, 11];
const sortedArray= [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const setHasValue = set => value => set.has(value);
const firstElement = sortedArray.find(setHasValue(new Set(unSortedArray)));
console.log(firstElement);
It would be a good idea to construct a look up table for unsorted array items. Such as
{ 54: true
, 23: true
, 55: true
.
.
11: true
}
This would be an O(k) task where k is the number of elements of the unsorted array. Then find the first item in the sorted array that returns true. This should be an O(n) task where n is the number of elements of the sorted array. Yielding a linear time solution.
This should do it.
function getFirst(usa,sa){
var h = usa.reduce((r,n) => (r[n] = true, r), {});
return sa.find(n => h[n]);
}
var r = getFirst([54,23,55,76,9,11], Array.from({length:100}, (_,i) => i+1));
console.log(r);
I have two arrays a and b.
Either array can have any number of items. However their length may not match.
I need the array lengths to match so I can zip the two array together.
For example:
a = [1, 2, 3, 4]
and
b = [1, 2]
Becomes:
a = [1, 2, 3, 4]
and
b = [1, 1, 2, 2]
I need b to match the length of a or vice versa to whatever one is longer length.
As well as to spread the values of the shorter array until matches the length of the longer array.
The spread on the shorter array would only contain the values present at start.
For example:
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
and
b = [1, 2]
Becomes
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
and
b = [1, 1, 1, 1, 1, 2, 2, 2, 2, 2]
Another example:
a = [21, 22, 23, 24, 25, 26, 27]
and
b = [39, 40, 41, 42]
Becomes:
a = [21, 22, 23, 24, 25, 26, 27]
and
b = [39, 39, 40, 40, 41, 41, 42]
SOLVED IT using Ramda
const a = [1, 2]
const b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
R.sort(R.gte, R.flatten(R.repeat(a, b.length / 2)))
Without relying on any libraries, this function will give you the desired result
const a = [21, 22, 23, 24, 25, 26, 27]
const b = [39, 40, 41, 42]
// a, b = longer array, shorter array
function spread(a, b) {
let result = null
if (a.length !== b.length) {
// target: array that needs to be spread
const [target, longest] = a.length > b.length ? [b, a] : [a, b]
// difference: amount target needs to be spread
const difference = longest.length - target.length
// check if elements need to be repeated more than twice
if (difference > target.length) {
result = [].concat(
...target.map((n, i) => {
if (typeof n !== 'string') {
return Array.from(n.toString().repeat(difference / 2)).map(Number)
}
return Array.from(n.repeat(difference / 2))
})
)
} else {
// repeat N elements twice until N <= difference/2
result = [].concat(
...target.map((n, i) => (i <= difference / 2 ? [n, n] : n))
)
}
// return the spread array
return result
}
// return original array if both arrays are same length
return b
}
spread(a, b) // => [ 39, 39, 40, 40, 41, 42 ]
Pure JavaScript solution that will extend a shorter array to the length of a longer one. The stretching is done by repeating each value in the shorter array and dynamically re-calculating how many times this is needed. So with lengths 10 and 3, the shorter array will have the first item repeated three times but the rest only two times in order to fit:
longer length: 10
shorter: [ 1, 2, 3 ]
/|\ /| |\
/ | \ / | | \
result: [ 1, 1, 1, 2, 2, 3, 3 ]
function equaliseLength(a, b) {
const [shorter, longer] = [a, b].sort((x, y) => x.length - y.length);
let remaining = longer.length;
const stretchedArray = shorter.flatMap((item, index) => {
//how many we need of this element
const repeat = Math.ceil(remaining / (shorter.length - index));
//adjust the remaining
remaining -= repeat;
//generate an array with the element repeated
return Array(repeat).fill(item)
});
//return to the order of the input:
//if `a` was the longer array, it goes first
//otherwise flip them
return longer === a ?
[longer, stretchedArray] :
[stretchedArray, longer]
}
console.log(printResult(
[1, 2, 3, 4],
[1, 2]
));
console.log(printResult(
[21, 22, 23, 24, 25, 26, 27],
[39, 40, 41, 42]
));
console.log(printResult(
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[1, 2]
));
console.log(printResult(
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[1, 2, 3]
));
console.log(printResult(
[1, 2, 3],
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
));
console.log(printResult(
[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
));
//just to make the display better
function printResult(a, b) {
const [resultA, resultB] = equaliseLength(a, b)
.map(x => x.map(y => String(y).padStart(2)))
.map(x => x.join("|"))
return `a = ${JSON.stringify(a)} b = ${JSON.stringify(b)}
result:
a = |${resultA}|
b = |${resultB}|`;
}
I have a list with items like:
var values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...];
I want, for every scroll, to add 15th new items and then to slice from the top another 15th elements.
Can you help me? Thanks!!!
Updated:
getMoreItems(items: any) {
var lastIndex: number;
if (items.visible.length) {
var lastItem: any = _.last(items.visible);
lastIndex = _.findLastIndex(items.allValues, { Name: lastItem.Name });
}
var startIndex = lastIndex + 1 || 0;
var endIndex = Math.min(startIndex + 15, items.allValues.length);
var newItems = items.allValues.slice(startIndex, endIndex);
if (items.visible.length > 30) {
items.visible = items.visible.slice(0, 15).concat(newItems);
} else {
items.visible = items.visible.concat(newItems);
}
}
var values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...];
values = values.splice(0,15); // remove first 15 items
values = values.concat([another 15 items]); // add next 15
And of course you can inline this:
values = values.splice(0,15).concat([x1...x2])
Something like this?
var numbers = [1,2,3,4,5,6,7,8,9,10];
numbers = numbers.slice(2).concat([11,12]);
console.log(numbers);
>> [ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]
if you have array on scroll you can reinitialize your array:
var old= [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
scroll=[32, 232,23, 232, 23, 232, 23,238, 92, 120];
old=scroll;
console.log(old);
and if you ahve items one by one then you can use pattern:
if you have array on scroll you can reinitialize your array:
var old= [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
old.push(next_value);
old.shift()
console.log(old);