Mapping an Array Based on Another Array - javascript

I'm working on a project where I need to change the values of one array should the first index of one of its nested arrays be found within the second array. For example:
Array One
[12345, [67890, 1], [09876, 2]]
Array Two
[
[
180547,
'180547 text',
'more text',
...etc
], [
67890,
'67890 text',
'more text',
...etc
],
...etc
]
I need to iterate through each of the nested arrays in Array One and check if the first value in each nested array is present in the any of the arrays in Array Two. From there, I need to copy Array Two's array, and replace the first value of the nested array in Array One.
I know that was probably a little confusing, so here's an example output of the above arrays:
Output
[12345, [[67890, '67890 text', 'more text', ...etc], 1], [09876, 2]]
ES6+ is preferred, but not necessary.
EDIT:
As asked for, so given -
Function jargon aside, here's the best I was able to come up with on my own:
gid.steal()
.then(dataset => {
let o = dataset.forEach(group => {
group.map((person, i) => {
i === 0 ? person : rows.forEach(row => {
row[0] === person[0] && row[row.length - 1] === '-3' ? [row, person[1]] : null
})
})
})
console.log(o)
})
.catch(err => rej(err))
//dataset would be Array One and rows would be Array Two
This returns undefined
I have a feeling I'm either trying to get too complicated/clever with it, or I'm totally out of bounds on this method.

Figured it out. It turns out I was definitely trying to be more complicated than I needed to be. I just needed some simple maps and a filter.
let arr1 = [
['john', 1, 2, 3, 4, '5'],
['jane', 1, 2, 3, 4, '5'],
['jane', 1, 2, 3, 4, '-3'],
['joe', 1, 2, 3, 4, '-3']
]
let arr2 = [
['number', ['jane', 1]]
]
const fx = data => {
return data.map(s => {
return s.map((t, u) => {
return u === 0
? t
: [arr1.filter(v => v[0] === t[0] && v.indexOf('-3') >= 0)[0], t[1]]
})
})
}
console.log(fx(arr2))

Related

What is the best way to check multidimensional array in typescript or javascript to detect duplicate values?

I have two dimensional array like below:
array = [ [ 1, 1 ], [ 1, 2 ], [ 1, 1 ], [ 2, 3 ] ]
I want to compare value in array index to see if they have duplicate values. For example
array[0] = [1,1];
array[1] = [1,2];
array[2] = [1,1];
We can see that value at index 0 and 2 are same that is [1,1]. So, in that case I want to have true flag. What is the most efficient way to do it? or What are different ways to do it? Any kind of suggestion or help would be great with bit of explanation. Thanks in advance.
You can achieve it by convert the inner array elements into a string just for the comparison purpose.
Demo :
const arr = [[ 1, 1 ], [ 1, 2 ], [ 1, 1 ], [ 2, 3 ]];
const stringConversion = arr.map((item) => JSON.stringify(item))
const duplicateElements = stringConversion.filter((item, index) => stringConversion.indexOf(item) !== index)
console.log(duplicateElements.length ? true : false);
So, what I think you can do is:
Cycle every element of the multidimensional array.
Then check if the two element are the same by accessing the "row" with the index 0 and index 1
I think you can use different way to loop the array, this is what I tried:
// DECLARATIONS
array = [[ 1, 1 ], [ 1, 2 ], [ 1, 1 ], [ 2, 3 ]];
// LOOPING THE ARRAY
for (row of array)
{
// RETURN TO CONSOLE OR WHATEVER THE BOOLEAN VALUE
console.log(row[0] == row[1]);
}
String to convert array to a one-dimensional array of strings and some to check if any element is duplicated:
const arr = [[1, 1], [1, 2], [1, 1], [2, 3]];
const result = arr.map(String).some((v, i, a) => a.indexOf(v) !== i);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

How to get all index of an array to new array

I have an array of arrays that I am trying to map. But I am having an issue with my mapping because mapping all indexes not just the one I want it to be mapping. I figured I can work my way around this by creating a new array of only of the data I am trying to map.
How can I push all index 2 into a new array? I have not been able to find an example of what I am attempting to do.
I am expecting an outcome of a new array that equals [231, 431, 481]
Here is an example of my code:
const array = [ ["name", 1, 231], [ "name", 2, 431], ["name", 3, 481] ]
console.log(array)
let percentage = array.map(function (num, i) {
return 100 * ((num - array[i - 1]) / (array[i - 1]));
});
You can do this
const array = [ ["name", 1, 231], [ "name", 2, 431], ["name", 3, 481] ]
const arrayNew = array.map(x => x[2])
// arrayNew === [231, 431, 481]
Check the inline comments
const array = [
["name", 1, 231],
["name", 2, 431],
["name", 3, 481],
];
// If you know, there will be 3 elements in array
console.log(array.map(([, , last]) => last));
console.log(array.map(({ 2: last }) => last));
// For any size of sub array, get the last element in map
console.log(array.map((arr) => arr[arr.length - 1]));

Filtering an array with objects with another array with strings

I have 2 arrays and I want to filter one of the arrays with another array.
2 arrays designed like this
array1= [{id:23},{id:11},{id:435}]
array2= [23, 435, 5]
I want to check and get items only if id of objects inside array1 is equal to one of the ids (string values ) in array2
I found a simple solution like this
var filtered=[1,2,3,4].filter(function(e){return this.indexOf(e)<0;},[2,4]);
but my case is a bit different, I dont know how to make return part, how can I get indexes of each array ?
var filtered=array1.filter(function(e){return e.id === ??},array2);
You could just look up the index by using the id property.
var array1 = [{ id: 23 }, { id: 11 }, { id: 435 }],
array2 = [23, 435, 5],
filtered = array1.filter(function (o) {
return array2.indexOf(o.id) > -1;
});
console.log(filtered);
ES6
var array1 = [{ id: 23 }, { id: 11 }, { id: 435 }],
array2 = [23, 435, 5],
filtered = array1.filter(({ id }) => array2.includes(id));
console.log(filtered);
You can use .filter and essentially check if the object id exists in array2. There are several ways to do that including .find and .findIndex. I would use .some which returns true if a single match is found.
array1.filter(obj => array2.some(id => id === obj.id));

expand and reorder an array of objects

i have and array
reservation1:[
{name:"8:30",active:true,dayindex:1},
{name:"jad",active:true,dayindex:3},
]
i need to expand the array to 9
and fill it with object with name null active false dayindex: between 0 and 10 in order
the output needed is
output =[
{name:"",active:false,dayindex:0}
{name:"8:30",active:true,dayindex:1}
...
i tried this for expanding
it worked for expanding but i couldnt reorder it as i wanted
You can sort you array after adding others elements:
var reservation = [
{name:"8:30",active:true,dayindex:1},
{name:"jad",active:true,dayindex:3},
{name:"tony",active:true,dayindex:4},
{name:"",active:false,dayindex:6}
];
var availabeDayIndex = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].filter(el => !reservation.map(it => it.dayindex).includes(el));
var sortField = 'dayindex';
reservation = [...reservation, ...Array.from(Array(9 - reservation.length), (val, key) => ({name: null, active: false, dayindex: availabeDayIndex[key]}))].sort((a, b) => a[sortField] - b[sortField]);
console.log(reservation);

find unique entries inside a multidimensional javascript array, order important dependent on level

What would be the most elegant solution to find all unique first level entries inside a multidimensional javascript array? There is only one important rule: the order of the entries is important only on the first level, but not important on the second level
For example, for the following array the script should return 4 unique entries (the first, the third, the fourth and the fifth):
[
[ [],[22],[1,13,17],[12],[] ],
[ [],[22],[17,13,1],[12],[] ],
[ [],[12],[1,13,17],[22],[] ],
[ [11],[12],[13],[14],[15] ],
[ [15],[14],[13],[12],[11] ]
]
PS. jQuery can be used as well.
First of all, here is a working JSFiddle for you to play around with: http://jsfiddle.net/missyalyssi/ro8o94nk/
Given an input array the function findUnique will return an array containing items that are unique according to your definition. So, for example:
[[8],[1,2,3],[9]] is a duplicate of [[8], [3,1,2], [9]] but it is not a duplicate of [[9], [3,1,2], [8]]
My main focus when writing this was to make it easy to read and understand.
function findUnique(input) {
let found = [];
let uniqueEls = new Set();
let hasDup = true;
for (let element of input) {
hasDup = found.length &&
found.every((el) => {return deepEqualsNaive(el, element)});
if (hasDup) {
uniqueEls.delete(element);
continue;
}
found.push(element);
uniqueEls.add(element);
}
return [...uniqueEls];
}
This function uses deepEqualsNaive to determine if two arrays are equal. Since object equality in javascript means that the arrays would point to the same memory location we need to build our own function to return true for what we are calling equal. Here, by equal we mean that they have the same elements even though they are not pointing to the same memory location, or appearing in the same order.
I have written this function recursively for readability I do not know the context that you are using this in. If you could overflow the stack then use an iterative version.
Here are some example inputs and what we would expect:
deepEqualsNaive([ [],[22],[1,13,17],[12],[] ], [ [],[22],[17,13,1],[12],[] ]) => true
deepEqualsNaive([ [],[22],[17,13,1],[12],[] ], [ [],[12],[1,13,17],[22],[] ]) => false
deepEqualsNaive([ [],[22],[1,13,17],[12],[] ], [ [],22,[17,13,1],[12],[] ]) => false
The function:
function deepEqualsNaive (input, clone) {
if (!Array.isArray(input) || !Array.isArray(clone)) return false;
if (input.length !== clone.length) return false;
var result = 0;
for (let elIdx = 0; elIdx < input.length; elIdx++) {
var tryDeep = true;
if (Array.isArray(input[elIdx])) tryDeep = deepEqualsNaive(input[elIdx], clone[elIdx]);
if (!tryDeep) return false;
result ^= input[elIdx];
result ^= clone[elIdx];
}
return result === 0;
}
If you're not all that worried about performance and just need something that works, you could use the constant depth you mentioned along with the string representation as a "fingerprint" of sorts (akin to Java's hashcode).
Then you use a Set to keep track of items you've not seen before, and add only those that are new.
function getUnique(rows) {
let unique = new Set();
let results = [];
for (let row of rows) {
// Fingerprint is the string representation of the row,
// with the inner-level sorted (as order doesn't matter).
// E.g., fingerprint of [ [8], [3, 2, 1], [9] ] is '[[8],[1,2,3],[9]]'
let fingerprint = JSON.stringify(row.map((cells) => {
return cells.concat().sort(); // Use concat to avoid sorting in place.
}));
// If we haven't seen this fingerprint before,
// add to the filter and the results list.
if (!unique.has(fingerprint)) {
unique.add(fingerprint);
results.push(row);
}
}
return results;
}
This, for example, will come up with...
> x = [
... [ [8], [3, 2, 1], [9] ],
... [ [7], [8, 3, 9], [1, 2] ],
... [ [8], [1, 2, 3], [9] ],
... ];
> getUnique(x);
[ [ [ 8 ], [ 3, 2, 1 ], [ 9 ] ],
[ [ 7 ], [ 8, 3, 9 ], [ 1, 2 ] ] ]
Obviously if your inner values are non-primitives (objects, arrays, etc) then this will fall over, but if you're dealing with numbers like your example, it should be fine.
If it's ok to have reference to the original array 'records' and inner arrays (that is, no deep copy), you can use something like:
function distinct(arr){
const res =[], //array with results
cmpArr = (a1,a2) => a1.length===a2.length && a1.every((i,ind) => a2[ind] === i),
cmpRec = (a1,a2) => [1,2,3].every(i=> cmpArr(a1[i],a2[i])); //compare 'records' for indices 1,2 and 3
for(let subarr of arr){
subarr[2].sort(); //NB, this alters the source array. If this is not allowed, a work around can be created
if(!res.some(r => cmpRec(r,subarr))) //check if 'res' doesn't have an entry , based on the cmpRec function
res.push(subarr);
}
return res;
}
//test:
let input = [
[ [],[22],[1,13,17],[12],[] ],
[ [],[22],[17,13,1],[12],[] ],
[ [],[12],[1,13,17],[22],[] ],
[ [11],[12],[13],[14],[15] ],
[ [15],[14],[13],[12],[11] ]
];
console.log(distinct(input).map(JSON.stringify));

Categories

Resources