So I am having a bit of difficulty trying to think of the best way of doing this in javascript. I want to remove an array of unsorted indexes from an array that was X number of elements. For example
var index = [ 0, 7, 10, 2, 5, 11]
array = [{field0: 0}, {field1: 1}, {field2: 2}, ... {field5: 5}, {field6: 6}...]
So I tried using a nested for loop with splice, but then when I splice, my array loses its indexing and screws up.
The end result should come out to be like
array = [{field1: 1}, {field3: 3}, {field4: 4}, .... {field6: 6} ...]
Any help would be greatly appreciated.
The solution to your problem is really a one-liner:
array = [00,11,22,33,44,55,66,77];
indexes = [1,7,5,3];
array = array.filter(function(_,i) { return indexes.indexOf(i) < 0 });
document.write('<pre>'+JSON.stringify(array,0,3));
If sorting the array of elements to remove is not an issue, you can just do the following:
var array = [{field0: 0}, {field1: 1}, {field2: 2}, {field3: 3}, {field4: 4}, {field5: 5}, {field6: 6}, {field7: 7}, {field8: 8}, {field9: 9}];
var indices = [0, 7, 2, 5];
indices.sort(function(a, b) {
if ( a > b ) {
return 1;
} else if ( b > a ) {
return -1;
} else {
return 0;
}
});
for (var i = 0, offset = 0; i < indices.length; i++, offset++) {
array.splice(indices[i] - offset, 1);
}
console.log(array);
And if for some reason you were unable to sort the array of indices to remove, you could keep track of the offset with the following:
var array = [{field0: 0}, {field1: 1}, {field2: 2}, {field3: 3}, {field4: 4}, {field5: 5}, {field6: 6}, {field7: 7}, {field8: 8}, {field9: 9}];
var indices = [0, 7, 2, 5];
var removedIndices = [];
function calcOffset(val) {
var numRemoved = 0;
for (var j = 0; j < removedIndices.length; j++) {
if (val > removedIndices[j]) {
numRemoved++;
}
}
return numRemoved;
}
for (var i = 0, offset = 0; i < indices.length; i++, offset++) {
var offset = calcOffset(indices[i]);
array.splice(indices[i] - offset, 1);
removedIndices.push(indices[i]);
}
console.log(array);
I would iterate through array (for/next loop) and at each element see if the number exist in index (index.indexOf(n)). If it does, push the element to a new temporary array.
when you are done, either copy the temp array back to array OR array.length = 0 and push the elements from the temp array back onto the original array.
something like this:
var index = [ 0, 7, 10, 2, 5, 11]
var array = [{field0: 0}, {field1: 1}, {field2: 2},{field3: 3}, {field4: 4}];
var tempArray = [];
for(var arrayIndex = 0;arrayIndex < array.length;arrayIndex++){
if(index.indexOf(arrayIndex) === -1)
{
tempArray.push(array[arrayIndex]);
}
}
array = tempArray;
You can try deleting them with delete array[index[count]] by looping as long as undefined is not a problem.
Or, you can set loop through all the elements in the array and set any element whose index is not present to false. Then, loop through them again and copy only the ones which are not false to new array.
newArray = new Array();
for (var i = 0; i < array.length; i++) {
for(var j=0; j<index.length; j++) {
if (index[j] == i) {
array[i] = false;
}
}
};
for (var i = 0; i < array.length; i++) {
if (array[i] != false) {
newArray[i] = array[i];
}
}
Related
This question already has answers here:
get only the unique value of an array
(5 answers)
Closed 3 years ago.
I am trying to get rid of duplicates from withing a array but I am trying to get rid of the original of those duplicates as well just leaving anything that has not been repeated more than once
Example:
const jsonarray = [{num: 1}, {num: 1}, {num: 2}, {num: 3}, {num: 5}, {num: 5}];
This is what I want the result to be
[{num: 2}, {num: 3}];
I have tried splicing with nested for loop but that did not work any help would be appreciated.
const jsonarray = [{num: 1}, {num: 1}, {num: 2}, {num: 3}, {num: 5}, {num: 5}];
// filter out all the elements that have the same num but different indexes
const filtered = jsonarray.filter((a, indexA) => !jsonarray.find((b, indexB) => b.num === a.num && indexA !== indexB));
console.log(filtered);
var track = jsonarray.length;
for(var i = 0; i < track; i++) {
var duplicate = false;
for(var j = 0; j < jsonarray.length; j++) {
if(i != j && jsonarray[i] == jsonarray[j]) {
duplicate = true;
jsonarray.splice(j, 1);
if(j < i) {
i--;
track--;
}
}
}
if(duplicate) {
jsonarray.splice(i, 1);
i--;
track--;
}
}
I'm trying to create an array of hashes in javascript. For instance;
[{id: "1", demo: 1, demo2: 2, demo3: 3}, {id: "2", demo: 1, demo2: 2, demo3: 3}, {id: "3", demo: 1, demo2: 2, demo3: 3}..]
I have loop through from 2 for loops but because the hash variable name is the same during the loop it writes on the previous one, not pushing it to array;
var rows = [];
var exc_hash = {};
for (k = 0; k < 2; k++) {
for (m = 1; m < 4; m++) {
var exc = ((data[m][k][1][2] == 'OK') ? data[m][k][1][0] : data[m][k][1][2]);
exc_hash["id"] = data[0][k];
exc_hash[(data[m][k][7])] = exc;
}
rows.push(exc_hash);
}
console.log(rows);
When I console log the rows, it prints;
[{id: "1", demo: 1, demo2: 2, demo3: 3}, {id: "1", demo: 1, demo2: 2, demo3: 3}]
The last hash written as for the first hash as well.
EDIT:
Thank you but when I use this like you show;
var rows = [];
for (k = 0; k < 2; k++) {
for (m = 1; m < 4; m++) {
var exc_hash = {
id: k
};
exc_hash['data'+m] = 'data'+m+k;
rows.push(exc_hash);
}
}
console.log(rows);
it prints;
0:{id: 0, data1: "data10"}
1:{id: 0, data2: "data20"}
2:{id: 0, data3: "data30"}
3:{id: 1, data1: "data11"}
4:{id: 1, data2: "data21"}
5:{id: 1, data3: "data31"}
However, I would like to get this;
0:{id: 0, data1: "data10", data2: "data20", data3: "data30"}
1:{id: 1, data1: "data11", data2: "data21", data3: "data31"}
How can I accomplish this?
This is a fairly classic problem. You're recycling the same object through each iteration of the loop so you're inserting the exact same object into the array.
To fix this, declare that internally:
var rows = [];
for (k = 0; k < 2; k++) {
for (m = 1; m < 4; m++) {
var exc_hash = {
id: data[0][k]
};
exc_hash[(data[m][k][7])] = ((data[m][k][1][2] == 'OK') ? data[m][k][1][0] : data[m][k][1][2]);
rows.push(exc_hash);
}
}
console.log(rows);
I need to split an array into several sub arrays and replace a certain character.
First I run a function to count the number of duplicates in the array. Then I build a new array with the values and the number of instances of the value.
Code:
angular.forEach($scope.financial, function(data) {
counts[data] = (counts[data] || 0)+1;
})
Result:
[4, {25: 4}, 5, {25: 1}, 3, {10: 1}, 4, {10: 1}]
What I am looking for is to split the array into several sub arrays and replace the colon with a comma.
Like this:
[[4,25,4],[5,25,1],[3,10,1],[4,10,1]]
Any suggestions?
That can be done with a simple loop. But, some checks for the integrity of the data would be advised if you can't guarantee the format of the input.
function getKey(o) {
for (var prop in o) {
if (o.hasOwnProperty(prop)) {
return prop;
}
}
}
var data = [4, {25: 4}, 5, {25: 1}, 3, {10: 1}, 4, {10: 1}];
var i = 0;
var output = [];
var key;
for (i = 0; i < data.length; i += 2) {
key = getKey(data[i + 1]);
output.push([data[i], parseInt(key, 10), data[i + 1][key]]);
}
//Print the output
console.log(output);
var el = document.createElement('div');
el.innerHTML = JSON.stringify(output);
document.body.appendChild(el);
The below mentioned converter function will accept the reponseArray of type [4, {25: 4}, 5, {25: 1}, 3, {10: 1}, 4, {10: 1}] and converts into subarray [[4,25,4],[5,25,1],[3,10,1],[4,10,1]]
fiddle
function converter(responseArray) {
var mainArray=[], subArray;
for (var i = 0; i < responseArray.length; i++) {
if(i%2 == 0) {
subArray= [];
subArray.push(responseArray[i]);
} else {
var obj = responseArray[i];
for(var key in obj) {
subArray.push(key * 1);
subArray.push(obj[key] * 1);
}
mainArray.push(subArray);
}
}
console.log(mainArray);
return mainArray;
}
I've got an array as below.
var FruitArr = [5, "Mango", 3, "Apple", 2, "Lychee", 1, "Banana", 4, "Pineapple"];
How can I sort the fruit names according to the number before it and add to an empty array? The array has been stored as position , item.
The expected output is
var newFruitArr = ["Banana", "Lychee", "Apple", "Pineapple", "Mango"];
EDIT:
The reason for having items as it is shown: In my actual code the fruit names are base64 url string which is created on the fly. The base64 creating depends based on the image. Therefore I couldn't think of a better way of adding the url strings in to the array. So I added items to the array as 'desired position', 'base64 string'. I thought of sorting them once all conversions are done. I did use .splice() which did not work as expected because of the above reason.
There is no need to sort, you already have the indexes in your input array.
Just preallocate your new array and fill it.
var fruits = [2, "apple", 1, "orange"],
fruitsLength = fruits.length;
var newFruitArr = new Array(fruitsLength / 2);
for (var i = 0; i < fruitsLength; i += 2)
newFruitArr[fruits[i] - 1] = fruits[i + 1];
Does this fit your need ?
function sort (arr) {
var min, minId = -1, output = [];
while (arr.length >= 2) {
for (var i = 0; i < arr.length; i += 2) {
if (arr[i] < min || minId == -1) {
minId = i;
min = arr[i];
}
}
output.push(arr[minId + 1]);
arr.splice(minId, 2);
minId = -1;
}
return output;
}
It search for the minimum number, push the corresponding fruit to the output and remove the couple from the input array, until there's nothing in it. Quite simple, surely not the most effective solution.
You have to convert your array to a form easy to use with sort method.
Here is the code to do so:
var result = [];
FruitArr.forEach(function (el, i) {
if (i % 2) result.push({value: el, weight: FruitArr[i-1]});
});
The result array will be:
[{value: "Mango", weight: 5}, {value: "Apple", weight: 3}, {value: "Lychee", weight: 2}, {value: "Bananna", weight: 1}, {value: "Pineapple", weight: 4}];
which easy to sort with sort method.
I actually prefer insertion-sort-algo to sort an array because of performance issues:
var arr = [5, "Mango", 3, "Apple", 2, "Lychee", 1, "Bananna", 4, "Pineapple"];
var groups = [];
for(var f=0; f < arr.length; f+=2)groups.push([arr[f],arr[f+1]]);
function insertion_sort(array){
for(var o=1; o < array.length;o++){
for(var i=o; i>0 && array[i][0] < array[i-1][0];i--){
var tmp = array[i];
array[i] = array[i-1];
array[i-1] = tmp;
}
}
return array;
}
insertion_sort(groups); // [[1, "Bananna"], [2, "Lychee"], [3, "Apple"], [4, "Pineapple"], [5, "Mango"]]
for hours i've been trying to figure out how to sort 2 array dependently.
Let's say I have 2 arrays.
First one:
array1 = ['zzzzz', 'aaaaaa', 'ccccc'];
and the second one:
array2 = [3, 7, 1];
I sort the first one with array1.sort(); and it becomes [aaaaaa, cccccc, zzzzzz]
now what I want is that the second one becomes [7, 1, 3]
I think it's quite simple but i'm trying to implement this in something a little more complex, im new and i keep mixing up things.
Thanks
I would "zip" them into one array of objects, then sort that with a custom sort callback, then "unzip" them back into the two arrays you wanted:
var array1 = ['zzzzz', 'aaaaaa', 'ccccc'],
array2 = [3, 7, 1],
zipped = [],
i;
for(i=0; i<array1.length; ++i) {
zipped.push({
array1elem: array1[i],
array2elem: array2[i]
});
}
zipped.sort(function(left, right) {
var leftArray1elem = left.array1elem,
rightArray1elem = right.array1elem;
return leftArray1elem === rightArray1elem ? 0 : (leftArray1elem < rightArray1elem ? -1 : 1);
});
array1 = [];
array2 = [];
for(i=0; i<zipped.length; ++i) {
array1.push(zipped[i].array1elem);
array2.push(zipped[i].array2elem);
}
alert('Sorted arrays:\n\narray1: ' + array1 + '\n\narray2: ' + array2);
Here's a working fiddle.
Here's a simple function that will do the trick:
function sortTogether(array1, array2) {
var merged = [];
for(var i=0; i<array1.length; i++) { merged.push({'a1': array1[i], 'a2': array2[i]}); }
merged.sort(function(o1, o2) { return ((o1.a1 < o2.a1) ? -1 : ((o1.a1 == o2.a1) ? 0 : 1)); });
for(var i=0; i<merged.length; i++) { array1[i] = merged[i].a1; array2[i] = merged[i].a2; }
}
Usage demo (fiddle here):
var array1 = ['zzzzz', 'aaaaaa', 'ccccc'];
var array2 = [3, 7, 1];
console.log('Before..: ',array1,array2);
sortTogether(array1, array2); // simply call the function
console.log('After...: ',array1,array2);
Output:
Before..: ["zzzzz", "aaaaaa", "ccccc"] [3, 7, 1]
After...: ["aaaaaa", "ccccc", "zzzzz"] [7, 1, 3]
Instead of two arrays of primitive types (strings, numbers) you can make an array of objects where one property of the object is string (containing "aaaaa", "cccccc", "zzzzzz") and another is number (7,1,3). This way you will have one array only, which you can sort by any property and the other property will remain in sync.
It just so happens I had some old code lying around that might do the trick:
function arrVirtualSortGetIndices(array,fnCompare){
var index=array.map(function(e,i,a){return i;});
fnCompare=fnCompare || defaultStringCompare;
var idxCompare=function (aa,bb){return fnCompare(array[aa],array[bb]);};
index.sort(idxCompare);
return index;
function defaultStringCompare(aa,bb){
if(aa<bb)return -1;
if(bb<aa)return 1;
return 0;
}
function defaultNumericalCompare(aa,bb){
return aa-bb;
}
}
function arrReorderByIndices(array,indices){
return array.map(
function(el,ix,ar){
return ar[indices[ix]];
}
);
}
var array1 = ['zzzzz', 'aaaaaa', 'ccccc'];
var array2 = [3, 7, 1];
var indices=arrVirtualSortGetIndices(array1);
var array2sorted=arrReorderByIndices(array2,indices);
array2sorted;
/*
7,1,3
*/
Sorry, I don't do 'fors'. At least not when I don't have to.
And fiddle.
Also, an alternative fiddle that sorts the results when given an array of objects like this:
given:
var list = [
{str:'zzzzz',value:3},
{str:'aaaaa',value:7},
{str:'ccccc',value:1}
];
outputs:
[
{str: "aaaaa", value: 7},
{str: "ccccc", value: 1},
{str: "zzzzz", value: 3}
]
Assumption:
The arrays are the same length (this is implied by your question)
the contents can be compared with > and < (true in your example, but I wanted to make it clear that it was assumed here)
So then we can use an insertion sort.
var value,len = array1.length;
for (i=0; i < len; i++) {
value = array1[i];
for (j=i-1; j > -1 && array1[j] > value; j--) {
array1[j+1] = array1[j];
array2[j+1] = array2[j];
}
items[j+1] = value;
}
Using a solution found here to find the new indices after sorting an array, you can apply those indices to array2 like so.
function sortWithIndices(toSort) {
for (var i = 0; i < toSort.length; i++) {
toSort[i] = [toSort[i], i];
}
toSort.sort(function(left, right) {
return left[0] < right[0] ? -1 : 1;
});
toSort.sortIndices = [];
for (var j = 0; j < toSort.length; j++) {
toSort.sortIndices.push(toSort[j][2]);
toSort[j] = toSort[j][0];
}
return toSort;
}
var array1 = ['zzzz', 'aaaa', 'cccc'];
var array2 = [3, 7, 1];
// calculate the indices of array1 after sorting. (attached to array1.sortIndices)
sortWithIndices(array1);
// the final array after applying the sorted indices from array1 to array2
var final = [];
// apply sorted indices to array2
for(var i = 0; i < array1.sortIndices.length; i++)
final[i] = array2[array1.sortIndices[i]];
// output results
alert(final.join(","));
JSFiddle Demo