i'm tryin' to explain what i want. I have two arrays:
my_array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
my_array_two = ["string", "string", "string", "string", "string", "string", "string", "string", "string", "string" ];
and i need to merge this arrays but in a specific way. The new array will be:
my_new_array = [1, 2, "string", 3, 4, "string", 5, "string", 6, "string", 7, "string", 8, "string", 9, "string", 10, "string", "string", "string" ]
The arrays length can be from 1 to 10.
I can't figure out how can i do this, i hope some help for this task.
Thanks in advance
The only pattern I can deduce from the specific input and output shown is to take two values from the first array, then one value from second array, then again two from the first, then alternate one from each until all values have been used from both arrays.
If that's right then the following code will do it:
// copy first input array into output array
var my_new_array = my_array.slice(0);
// loop over second array
for (var i = 0, j = 2; i < my_array_two.length; i++){
// insert next item into output at position j
my_new_array.splice(j, 0, my_array_two[i]);
// figure out next position to insert
j += (j < 4) ? 3 : 2;
}
If this is an original algorithm, your best best would be too write your own sort algorithm to merge the two.
Not sure what the specific pattern is, but as far as the basic algorithm, I would recommend something like this:
var combined_array = [];
var index1 = 0, index2 = 0;
while ((index1 < my_array.length) && (index2 < my_array_two.length)) {
if (/*you're at the end of either array*/) {
// take the next element from the other one.
}
else {
if (compare(my_array[index1], my_array_two[index2])) {
combined_array.push(my_array[index1]);
++index1;
}
else {
combined_array.push(my_array_two[index2]);
++index2;
}
}
}
Where compare is some function you write that looks a both values and returns true if the first one should come before the second.
Related
I want delete array from array of arrays without iterate on them.
the first array is like this :
array1 = [
[
[{"id":"A1","y":12},{"id":"A4","y":12}],
[{"id":"A2","y":1}],
[{"id":"A3","y":6}]
]
the second array is :
array2 = [{"id":"A1","y":12},{"id":"A4","y":12}]
I use javascript and i want delete array2 from array1.
So sorry for wrong description by the way i found that in my exemple the second array array is
array2 = [{ "id": "A1", "y": 12 }, { "id": "A4", "y": 2 }]
So the two arrays have just one columns which is equal. How i can delete array1 from array2 even they have just one attribute which is equal ?
Thank you.
splice is usually used to remove a particular item from the array. I think you want to do something like this:
var array = [
[{"name": "sik", "gender": "male"}],
[{"name": "sug", "gender": "female"}],
[{"name": "hyd", "gender": "male"}]
];
// it removes the second array from the array: removes the female one.
array.splice( 1, 1 );
Description: The function splice takes two arguments, first one is for the index of item, and second one until how much you want to delete.
For Example: splice( 2, 5 ) - means that: from the index 2, keep deleting until 5 items.
Hope this helps, Thanks.
Feels weird, but you can check every element of the array and match to the second array. Either way you need to iterate through your array. You can't simply type array1[i] == array2, you need to check it differently. A hack is to stringify them as JSON and compare strings, but there are other methods you can use to compare arrays.
Here is a simple demo with a for loop
array1 = [
[{ "id": "A1", "y": 12 }, { "id": "A4", "y": 12 }],
[{ "id": "A2", "y": 1 }],
[{ "id": "A3", "y": 6 }]
]
array2 = [{ "id": "A1", "y": 12 }, { "id": "A4", "y": 12 }]
l = array1.length
for (var i = 0; i < l; i++) {
// if arrays match
if (JSON.stringify(array1[i]) == JSON.stringify(array2)) {
// delete the element at `i` position
array1.splice(i, 1);
i--;
l--;
// break; // if you can guarantee that no more instances will occur
}
}
console.log(array1)
In Plain Javascript, we cannot filter them. This will work if u are dealing with valued datatypes. Here you are comparing arrays which are a referenced datatype. so here we need to write our own search stack
function searchForArray(haystack, needle){
var i, j, current;
for(i = 0; i < haystack.length; ++i){
if(needle.length === haystack[i].length){
current = haystack[i];
for(j = 0; j < needle.length && needle[j] === current[j]; ++j);
if(j === needle.length)
return i;
}
}
return -1;
}
var arr = [[1,3],[1,2]];
var n = [1,3];
console.log(searchForArray(arr,n));
You can refer this question which has some reference resources too.
Check whether an array exists in an array of arrays?
I know you asked for a solution without iteration, but i just thought to give an idea of references which may be useful for u.
I have an array y like this:
var y = [1, 2, 3, 4];
And I would like to iterate through the array, but exclude some indexes. The indexes are saved in second array
var x = [1,3];
So, I want to write each numbers from an array y, but not the numbers on the position 1,3, which come from array x
I tried to skip the numbers on these positions, but with no success. Could you please help me?
Here is what I tried
for (var i = 0; i < y.length; i++) {
for (var j = 0; j < x.length; j++) {
if (i === x[j]) {
continue;
}
}
console.log(y[i]);
}
Short answer
Prefer using filter over a loop
const xs = [ 1, 2, 3, 4, 5 ] // array of values
const ys = [ 1, 3 ] // indices to skip
// using `filter`
const zs = xs.filter((_, i) => !ys.includes(i))
console.log(zs)
//=> [ 1, 3, 5 ]
Long answer
When possible, you don't want to be using a loop because it can hurt the ability to understand your code taking a procedural approach over a declarative approach. You can instead use a higher-order function like Array.prototype.filter to keep the values you want. The return value of the function passed into filter needs to return a boolean of what to keep. In JavaScript, the filter function is of binary arity, meaning it takes two arguments, with the first argument being the array element and the second being the index. We can ignore the array element value as it is only the index we need to check (this is why the function starts with (_, ...) to drop the first argument).
Array.prototype.includes is a function on the array prototype that lets you know if the array contains a value (i.e. [0].includes(0) === true and [0].includes(1) == false).
Putting these two concepts together, we can iterate over the first array, xs, ignoring the values but using the index to see if it's included in our blacklisted indices array, ys.
If we looked at this as a map function, instead of filter that included our value
xs.map((v, i) => [ v, !ys.includes(i) ])
//=> [ [ 1, true ], [ 2, false ], [ 3, true ], [ 4, false ], [ 5, true ] ]
We can see which values will be true. And if we remember, filter keeps our true values [ 1, 3, 5 ].
You could use the Array.includes() method.
var list = [1,2,3,4];
var skipIndexes = [1,3];
for (var i = 0; i< list.length; i++) {
if (! skipIndexes.includes(i)) {
console.log(list[i]);
}
}
Looks like you were pretty close, but you don't need the inner loop. Just check if the index you're on (i) is one of the members of the array x, and if so, continue. You can do that using the array .includes method, or indexOf if you don't have es6 support.
var y = [1, 2, 3, 4];
var x = [1,3];
for (var i = 0; i < y.length; i++) {
if (x.includes(i)) continue; // Or if not es6 use: `x.indexOf(i) !== -1`
console.log(y[i]);
}
This prints 1 and 3, which are the items of the array y in the 0th and 2nd indices respectively (since we skipped indices 1 and 3).
I am creating a function which takes in a number value as a parameter. From there, the goal is to detect if three numbers occured in a row, for example 3415633356 would pass as true and 3562455 would not.
I am doing something wrong in my function as scenarios which should be passing as true are not. The end goal of detecting if three numbers in a row occured can be done in any way.
By the way, I am new to programming and just starting out so I'm trying to increment my knowledge as I practice these things. If you can breakdown why your suggesstion works and what I am doing wrong instead of just providing the sole answer, that would be hugely appreciated. Many thanks!
var testNumbers = function(num1){
var stringOne = num1.toString();
var num1array = stringOne.split("");
var tripleNum = [];
num1array.reduce(function(a,b){
if (a===b){
tripleNum.push(a);
}
})
if (tripleNum.length >= 3){
console.log(tripleNum);
} else {
console.log("There wasnt a case of three straight triple numbers occuring");
}
}
This can also be done with a regex :)
var testNumbers = function(num1){
var stringOne = num1.toString();
var regEx = /111|222|333|444|555|666|777|888|999|000/;
if (regEx.test(stringOne)){
console.log(stringOne.match(regEx)[0]);
} else {
console.log("There wasnt a case of three straight triple numbers occuring");
}
}
I would keep a counter that gets increased every time a new number equals a past number. If that count gets to three we quite and return true. Otherwise if the loop ends, we return false. For example:
function count3(arr) {
// initialize a counter
let count = 1
// loop through the array, starting with the second
// element, so we can compare it to the first
for (let i = 1; i < arr.length; i++) {
// does the count equal the previous?
// if so increase it, otherwise set it back to 1
count = arr[i] === arr[i - 1] ? count + 1 : 1 // <-- ternary operator
// see if we're done
if (count === 3) return true
}
// never reached three
return false
}
// try it out
var arr = [3, 3, 4, 1, 5, 6, 3, 4, 3, 5, 6, 5]
console.log(count3(arr))
var arr = [3, 3, 4, 1, 5,5,5, 6, 3, 4, 3, 5, 6, 5]
console.log(count3(arr))
// make sure it works when array ends with three
var arr = [ 5, 6, 7, 3, 3, 3]
console.log(count3(arr))
// with strings too?
console.log(count3('34156335666'))
In NodeJS, I created the following two scripts, both of them was intended to remove even numbers from an array.
This is my 1st script:
#!/usr/bin/nodejs
var myarr = [2,3,5,1,6,2,28,5,7,90,3];
console.log(myarr);
for(var i in myarr){
if(myarr[i] % 2 == 0){
myarr.splice(i,1);
--i;
}
}
console.log(myarr);
Output for the first script was following:
[ 2, 3, 5, 1, 6, 2, 28, 5, 7, 90, 3 ]
[ 3, 5, 1, 2, 5, 7, 3 ]
In 2nd script, I changed for..in loop to for(;;) loop as follows:
#!/usr/bin/nodejs
var myarr = [2,3,5,1,6,2,28,5,7,90,3];
console.log(myarr);
for(var i=0;i<myarr.length;i++){
if(myarr[i] % 2 == 0){
myarr.splice(i,1);
--i;
}
}
console.log(myarr);
I got following output for the 2nd script:
[ 2, 3, 5, 1, 6, 2, 28, 5, 7, 90, 3 ]
[ 3, 5, 1, 5, 7, 3 ]
Although my intention was the same, two for loops gave me different outputs. I figured out that, in my first script, if there are two adjacent even numbers exist in the original array, if condition seems to be applied for the first even number only where the second even number is skipped. I would really appreciate if anybody can explain this difference clearly.
What you're doing is wrong. You're removing keys from the array whilst looping through the same array. Your for...in loop will only ever perform 7 iterations, as 4 of your keys are spliced from the array whilst the array is still being iterated through, whereas your for(;;) loop will always perform all 11 iterations as this is defined at the beginning (myarr.length).
You should define a second array to use for your results instead:
for...in
var myarr = [2,3,5,1,6,2,28,5,7,90,3],
resultarr = [];
console.log(myarr);
for(var i in myarr){
if(myarr[i] % 2 != 0){
resultarr.push(myarr[i])
}
}
console.log(resultarr);
-> [3, 5, 1, 5, 7, 3]
for(;;)
var myarr = [2,3,5,1,6,2,28,5,7,90,3],
resultarr = [];
console.log(myarr);
for(var i=0;i<myarr.length;i++){
if(myarr[i] % 2 != 0){
resultarr.push(myarr[i]);
}
}
console.log(resultarr);
-> [3, 5, 1, 5, 7, 3]
As an ending note, you shouldn't use the for...in loop for iterating through arrays anyway. This answer details why this is a bad idea.
I have a table array which looks like this:
tablearray =
[
{'column1': 1, 'column2': 1, 'column3': 1, 'column4': 2},
{'column1': 1, 'column2': 2, 'column3': 3, 'column4': 4},
{'column1': 2, 'column2': 0, 'column3': 4, 'column4': 6}
]
I'm trying to make a function which takes the table array and an array of column names and makes a new object indexed by the column values. So
newObject = indexByColumnValues(tablearray, ['column1', 'column2']);
should result in an object like
newObject =
{
1:
{
1: {'column1': 1, 'column2': 1, 'column3': 1, 'column4': 2},
2: {'column1': 1, 'column2': 2, 'column3': 3, 'column4': 4}
}
2:
{
0: {'column1': 2, 'column2': 0, 'column3': 4, 'column4': 6}
}
}
So
newObject[1][1]['column3'] = 1
newObject[1][2]['column4'] = 4
etc...
If the number of columns in the column name array (['column1', 'column2'] above) is known, the solution is not hard. But if I allow for any number of column names in this array, it becomes more difficult as there is indefinite recursion
newObject[tablearray[columnNameArray[0]][tablearray[columnNameArray[1]][tablearray[columnNameArray[2]]...
Here is one attempt. I tried to use a pointer to point to the dimensional depth of the newObject array. First, pointer = newObject. Then pointer = newObject[...[0]]. Then point = newObject[...[0]][...[1]]. And so on. This builds the object properly but then I do not have a way to assign a value to newObject[...[0]]...[...[k]].
function indexByColumnValues(object, columnNameArray)
{
var newObject = {};
for(i in object)
{
var index=[];
for(j in columnNameArray)
{
index.push(object[i][columnNameArray[j]]);
}
var pointer = newObject;
for(j in index)
{
if(pointer[index[j]] == undefined)
{
pointer[index[j]] = {};
}
pointer = pointer[index[j]];
}
//now pointer points to newObject[index[0]][index[1]]...[index[k]]
//but I need to set newObject[...] above to be object[i]. How?
//pointer = object[i]; //won't work
}
return newObject;
}
Any help or hints would be great here. Thanks.
You mention recursion, but you don't use it in your code. This is a classic situation where recursion is the right tool. Here's one implementation:
function indexByColumnValues(table, cols) {
// get the column we're indexing
var col = cols[0],
index = {},
x, val;
// find all values
for (x=0; x<table.length; x++) {
val = table[x][col];
// add to index if necessary
if (!index[val]) index[val] = [];
// push this row
index[val].push(table[x]);
}
// recurse if necessary
if (cols.length > 1) {
for (x in index) {
if (index.hasOwnProperty(x)) {
// pass the filtered table and the next column
index[x] = indexByColumnValues(
index[x],
cols.slice(1)
);
}
}
}
return index;
}
Note that, as #jfriend00 notes, you want the "leaf" of your index to be an array of matching rows, not a single object - it's just coincidence that in your example you only have one matching row for your given data and set of columns. Usage:
indexByColumnValues(tablearray, ['column1','column2']);
Output:
{
"1":{
"1":[
{"column1":1,"column2":1,"column3":1,"column4":2}
],
"2":[
{"column1":1,"column2":2,"column3":3,"column4":4}
]
},
"2":{
"0":[
{"column1":2,"column2":0,"column3":4,"column4":6}
]
}
}
JsFiddle: http://jsfiddle.net/RRcRM/3/