How to remove a duplicate array from inside a nested array? - javascript

I would like to remove duplicated arrays from a 2D array.
For example I have this 2D array:
[[-1,0,1],[-1,-1,2],[-1,0,1]]
and I want to remove the duplicate to only have this:
[[-1,0,1],[-1,-1,2]]
I tried:
arr.filter((v, i, a) => a.indexOf(v) == i)
but this only works for primitive data types, not objects like arrays.

You can use Set method. The Set object stores unique values of any type, and automatically removes duplicates.
First convert all the sub arrays into string which can be compared. Then add them to Set to remove duplicates. Then convert the Set of strings to array by using Array.from(). At last parse the JSON object.
let arr = [[-1,0,1],[-1,-1,2],[-1,0,1]];
let uniqueArr = Array.from(new Set(arr.map(JSON.stringify))).map(JSON.parse);
console.log(uniqueArr); // output: [[-1,0,1],[-1,-1,2]]

This should remove duplicates and retain the original order; that is, it will remove the duplicates in place. Of course, I didn't test every possible case and there may be a more clever way to accomplish the same.
let aOrig = [[-1,0,1],[-1,0,1],[-1,-1,2],[-1,-1,2],[-1,0,1],[2],[-1,0,1,1],[-1,0],[2]],
a = new Array(),
c = new Array()
order = new Array();
aOrig.forEach( (v,i) => a.push([v.toString(),i]) );
a.sort((a,b) => a[0] < b[0] );
//a.forEach ( v => console.log(v[0].toString() + " : " + v[1]));
order.push(a[0][1]);
for (i=1, l=a.length; i < l; i++) {
if ( a[i][0] != a[i-1][0] ) {
order.push(a[i][1]);
}
}
//console.log(order.toString());
order.sort().forEach( v => c.push( aOrig[v] ) );
console.log('---------');
c.forEach( v => console.log(v.toString()) );

Related

Is there an efficient way to add an Array element's original index value as a property when sorting by another property in JavaScript?

AI have an Array that I am sorting by title property:
theArray.sort(function(a, b) {
var titleA = a.title.toLowerCase();
var titleB = b.title.toLowerCase();
return (titleA < titleB) ? -1 : (titleA > titleB) ? 1 : 0;
});
That works fine, but in addition to getting the sorted Array I'd like to also preserve the original Array index values for another purpose (they point to yet another Array). I'd like to store that as a property .idx in each element of the Array.
Of course I could simply add that property before sorting, by doing this:
for (var i=0; i<theArray.length; i++) {theArray.index = i);
This would be somewhat wasteful in this case because I don't always need to sort the Array. And when originally creating the Array it's coming from some JSON that doesn't have that property included. So I was thinking it might be best if I could add the property while sorting.
Any ideas? Thanks.
Instead of sorting the original array, you could sort an array of indicies:
const getTitle = i => theArray[i].title.toLowerCase();
const indicies = theArray.map((_, i) => i);
indicies.sort((indA, indB) => getTitle(indB).localeCompare(getTitle(indA)));
Then, when you need to do something with the "sorted" array, iterate over the indicies and access theArray[i]. When you need to do something with the sorted indicies, just iterate over the indicies array.
Create a new array when sorting, using spread will help:
const newArray = [...theArray].sort(function(a, b) {
var titleA = a.title.toLowerCase();
var titleB = b.title.toLowerCase();
return (titleA < titleB) ? -1 : (titleA > titleB) ? 1 : 0;
});

Sort array elements on JavaScript

I have an array, each subarray of which contains different positions in different order:
[
["apple(2)", "banana(5)"],
["peach(3)", "banana(1)"],
["apple(1)"]
]
I need to sort it on JavaScript (ES6) and i expect to get an array like this:
[
["apple(2)", "banana(5)", "peach(0)"],
["apple(0)", "banana(1)", "peach(3)"],
["apple(1)", "banana(0)", "peach(0)"]
]
Order of each subarray should be the same. If subarray don't have some position, i need to add it with 0 value. Can i using something like map() or sort() function or need to compare it manually?
Here is functional programming approach, using a Map and reduce:
const data = [['apple(2)', 'banana(5)'],['peach(3)', 'banana(1)'],['apple(1)'],];
// Create a Map with default values for each name, i.e. with "(0)":
let names = new Map(data.flat().map(item => [item.replace(/\d+/, ""), item.replace(/\d+/, "0")]));
let result = data.map(row =>
[...row.reduce((map, item) =>
map.set(item.replace(/\d+/, ""), item), // Overwrite default
new Map(names) // Start with clone of original Map
).values()]
);
console.log(result);
You have to loop over to get the keys used. You then have to loop over a second time to get the fill in the missing keys. There are many ways of doing it, this is one.
var data = [
["apple(2)", "banana(5)"],
["peach(3)", "banana(1)"],
["apple(1)"]
];
// match string and number
var re = /([^(]+)\((\d+)\)/;
// Loop over and find all of the keys
var grouped = data.reduce((info, subset, index) => {
subset.forEach(item => {
// find the key and count
var parts = item.match(re);
// have we seen this key?
if (!info[parts[1]]) {
// if not create an array
info[parts[1]] = Array(data.length).fill(0);
}
// set the key index with the count
info[parts[1]][index] = parts[2];
})
return info;
}, {});
// loop over the groups and fill in the set
Object.entries(grouped).forEach(([key, counts], colIndex) => {
counts
.forEach((cnt, rowIndex) => {
data[rowIndex][colIndex] = `${key}(${cnt})`;
})
});
console.log(data);
First get the unique words. Then traverse array of arrays to check if the word is present or not. If it is not present then make the word according to your condition and if present then put the original word to the tmp array. At last sort it for each iteration. By the way, I used regex replace method to get the word.
const data = [
['apple(2)', 'banana(5)'],
['peach(3)', 'banana(1)'],
['apple(1)'],
];
const words = [...new Set(data.flat().map((x) => x.replace(/[^a-z]/gi, '')))];
const ret = data.map((x) => {
const tmp = [];
const newX = x.map((y) => y.replace(/[^a-z]/gi, ''));
for (let i = 0, l = words.length; i < l; i += 1) {
if (newX.includes(words[i])) tmp.push(x.shift());
else tmp.push(`${words[i]}(0)`);
}
return tmp.sort();
});
console.log(ret);

Puh array in empty array that create before

I push two Array in one Array But can't use them as a string,This result in bellow about two arrays in one array :
Array(0) [] //This is empty array that I create before and push these two array bellow to them
length:2
0:Array(1) ["cfdb9868-0f69-5781-b1e4-793301280788"]
1:Array(1) ["cfdb9868-0f69-5781-b1e4-793301280788"]
and I create a for for access them but I can ! I write this code "
for(var index = 0 ; index < Array.length ; ++index) {
let Each_String_In_Brackets = Array[index] ;
console.log(Each_String_In_Bruckets);
}
Why is this happen!
I mean Why when we push array in empty array can't access them!
I want to access the content of them, I have a string In each bracket.
var arr = [];
arr.push(["cfdb9868-0f69-5781-b1e4-793301280788"]);
arr.push(["cfdb9868-0f69-5781-b1e4-793301280788"]);
//assuming inside array always will be one element:
arr.forEach((item)=>{ console.log(item[0])})
//if inside array may be multiple elements, then use this
arr.forEach((item, index)=>{
item.forEach((child)=>{ console.log(child)})
})
pushing a full array into another array makes it a 2D array ( at the indexes where you push another array ) so for example if I have the first array
BArray[]
But if I push another array into it
BArray2 = [1,2,3,4];
BArray.push(Array2);
We would not be able to access it just by
BArray[0]
This would return the entire array2 rather the content of array2 at index 0.
Therefore you would do this
BArray[0][0]
So this would give us ( from your array ) "cfdb9868-0f69-5781-b1e4-793301280788"
If you would like to just dump out the content of BArray2 into BArray
You can use the spread operator.
BArray[...BArray2];
( Also I would not use Array as variable name ! It can be confusing as new Array(10); is a way of creating arrays and having arrays with that name isn't best practice ! )
Hope this helps !
You are pushing array in array, so you must access as 2D array:
var array = [];
var arrayString1 = ["StringInArray1"],
arrayString2 = ["StringInArray2"];
array.push(arrayString1);
array.push(arrayString2);
console.log(JSON.stringify(array));
array.forEach(arrayItem => {
console.log("StringInArray: " + arrayItem[0]);
})
Or maybe you want to append array:
var array = [];
var arrayString1 = ["StringInArray1"],
arrayString2 = ["StringInArray2"];
[].push.apply(array, arrayString1);
[].push.apply(array, arrayString2);
console.log(JSON.stringify(array));
array.forEach(arrayItem => {
console.log("StringInArray: " + arrayItem);
})

How to convert string array to JSON array in Javascript?

I have string array like this:
"[totRev=248634.29858677526, totEBITDA=34904.9893085068, EBITDA_Operating_Cash_Flow_Margin=0.140386863387, debt_Service_Coverage_Ratio=16.7793849967, gross_Debt_to_EBITDA=0.3626422278, gross_Debt=50632.09233331651, cash_Available_for_Debt=102746.09168349924, debt_Servicing_Amount=6123.352655871018]"
How do I convert this either into a JSON Array or a JSON object like
{totRev:'248634.29858677526',....etc}
Use substring, split and reduce
str.substring( 1,str.length - 1 ) //remove [ and ] from the string
.split(",") //split by ,
.reduce( (a,b) => (i = b.split("="), a[i[0]] = i[1], a ) , {} );
Reduce explanation
Split b (element in the array such as totRev=248634.29858677526) by =
Assign the first item in the array as key to a (accumulator initialized as {}) and value as second item of the array
Return a
Demo
var str = "[totRev=248634.29858677526, totEBITDA=34904.9893085068, EBITDA_Operating_Cash_Flow_Margin=0.140386863387, debt_Service_Coverage_Ratio=16.7793849967, gross_Debt_to_EBITDA=0.3626422278, gross_Debt=50632.09233331651, cash_Available_for_Debt=102746.09168349924, debt_Servicing_Amount=6123.352655871018]";
var output = str.substring(1,str.length-1).split(",").reduce( (a,b) => (i = b.split("="), a[i[0].trim()] = i[1], a ) , {} );
console.log(output);

Javascript - Get Array of indices for 'WILL BE' relationship after sort

I have a very simple question. Say I have an array
a = [10,40,30,20,60,50]
After sorting, it would be (assuming I use sort_a = a.sort())
sort_a = [60,50,40,30,20,10]
I want to create an array of indices from a which specify which location in the sorted array that element WILL BE after sorting. From the above example, the result would be
a_sortedindices = [6, 3, 4, 5, 1, 2]
..meaning 10 is in the 6th position when sorted, 40 is in the 3rd position... etc
Pair the values with their current indices
Sort the array of pairs based on the original values
Combine the pairs with their new indices
Sort the new array based on the original indices
Obtain the new indices from the sorted array
let values = [10,40,30,20,60,50];
let indices = values
.map((v, i) => ({ v, i }))
.sort((l, r) => r.v - l.v)
.map(({v, i}, i2) => ({ v, i, i2 }))
.sort((l, r) => l.i - r.i)
.map(p => p.i2);
console.log(indices);
This results in an array of 0-based indices because JavaScript uses 0-based indices. If you want 1-based indices like in your question, you can change p.i2 to p.i2 + 1 in the second to last line.
One of the ways, apart from many to achieve this:
1) Transform the array into another with old indices
2) Sort the array in descending order
3) Create an answer array since you now know the old and new indices.
let a = [10,40,30,20,60,50];
let transformed = a.map((v,i)=> {
return {num:v,old:i};
});
transformed.sort((a,b)=> {
return b.num - a.num;
});
let ans = [];
transformed.forEach((v,i) => {
ans[v.old] = i+1;
});
console.log(ans);
Not sure if this is a trick question or if you're trying to find the most minimal method for achieving this, but you basically already have it. This is what I came up with:
var a = [10,40,30,20,60,50];
var sort_a = a.slice(0).sort((a1,a2) => a2 - a1);
var a_sortedindices = a.map( a1 => sort_a.indexOf(a1) + 1 );
console.log(a_sortedindices);
Walking through it, I'll explain each part.
First, off you have to sort it. Looks like you need reverse sorting, so we'll add an arrow function describing a reverse sort, but before we do that, we'll also clone the array, otherwise we'll lose the original indexes of the values. .slice(0) is a nice way to return a clone of an array
var sort_a = a.slice(0).sort((a1,a2) => a2 - a1);
Then we'll map each value of the origin array. .map() is nice and easy to quickly manipulate each element in an array. We use .indexOf() to figure out where it was at in the original array. We add one to that value because you're not using zero-based indexing.
var a_sortedindices = a.map( a1 => sort_a.indexOf(a1) + 1 );
And voila. You have the sorted indexes.
A naive way of doing this job could be;
var arr = [10,40,30,20,60,50],
idx = arr.map(function(n){return this.indexOf(n)+1;}, arr.slice().sort((a,b) => b-a));
console.log(idx);
where the this argument for the .map() function callback is arr.slice().sort((a,b) => b-a)
// the array to be sorted
var list = [10,20,30,40];
// temporary array holds objects with position and sort-value
var mapped = list.map(function(el, i) {
return { index: i, value: el };
})
// sorting the mapped array
mapped.sort(function(a, b) {
return b.value - a.value;
});
// you can then remap the sorted mapped array to hold just the indices
P.S.: For future reference MDN is your friend

Categories

Resources