Swapping Array elements with Keys - javascript

Im trying to swap two array elements in an array that looks like this
[18785:Object, 22260:Object, 22261:Object, 22262:Object, 22263:Object]
I used the following code:
that.moveMediumDown = function(mediumID){
var arrKeys = new Array();
for (key in that.data.medium) {
arrKeys.push(parseInt(key));
}
for (var i = 0; i < arrKeys.length; i++){
if (arrKeys[i] === parseInt(mediumID)) {
//swap Medium
var tmpMedium = that.data.medium[arrKeys[i]];
that.data.medium[arrKeys[i]] = that.data.medium[arrKeys[i + 1]];
that.data.medium[arrKeys[i + 1]] = tmpMedium;
break;
}
}
//build new array with correct ids
var tmpMediumArray = new Array();
for (var j = 0; j < arrKeys.length; j++){
tmpMediumArray[arrKeys[j]] = that.data.medium[arrKeys[j]];
}
}
The problem is when I swap the content of the two array elements, the key stays the same. But I need also to swap the key.
So i tried to build a new array with the correct keys but then I get an Array with 22263 elements. Most of them are undefined and only the 5 are correct.
Is there any method to do this without getting such a big array?
Thanks in advance for your help.

Checkout the array_flip function.
It allows you to swap keys with the elements:
array_flip( {a: 1, b: 1, c: 2} );
becomes
{1: 'b', 2: 'c'}

Related

Algorithm to sort an array in JS

I have an array
var arr= [
["PROPRI","PORVEC"],
["AJATRN","PROPRI"],
["BASMON","CALVI"],
["GHICIA","FOLELI"],
["FOLELI","BASMON"],
["PORVEC","GHICIA"]
] ;
And I'm trying to sort the array by making the second element equal to the first element of the next, like below:
arr = [
["AJATRN","PROPRI"],
["PROPRI","PORVEC"],
["PORVEC","GHICIA"],
["GHICIA","FOLELI"],
["FOLELI","BASMON"],
["BASMON","CALVI"]
]
The context is : these are somes sites with coordinates, I want to identify the order passed,
For exemple, I have [A,B] [C,D] [B,C] then I know the path is A B C D
I finally have one solution
var rs =[];
rs[0]=arr[0];
var hasAdded=false;
for (var i = 1; i < arr.length; i++) {
hasAdded=false;
console.log("i",i);
for (var j = 0, len=rs.length; j < len; j++) {
console.log("j",j);
console.log("len",len);
if(arr[i][1]===rs[j][0]){
rs.splice(j,0,arr[i]);
hasAdded=true;
console.log("hasAdded",hasAdded);
}
if(arr[i][0]===rs[j][1]){
rs.splice(j+1,0,arr[i]);
hasAdded=true;
console.log("hasAdded",hasAdded);
}
}
if(hasAdded===false) {
arr.push(arr[i]);
console.log("ARR length",arr.length);
}
}
But it's not perfect, when it's a circle like [A,B] [B,C] [C,D] [D,A]
I can't get the except answer
So I really hope this is what you like to achieve so have a look at this simple js code:
var vector = [
["PROPRI,PORVEC"],
["AJATRN,PROPRI"],
["BASMON,CALVI"],
["GHICIA,FOLELI"],
["FOLELI,BASMON"],
["PORVEC,GHICIA"]
]
function sort(vector) {
var result = []
for (var i = 1; i < vector.length; i++) result.push(vector[i])
result.push(vector[0])
return (result)
}
var res = sort(vector)
console.log(res)
Note: Of course this result could be easily achieved using map but because of your question I'm quite sure this will just confuse you. So have a look at the code done with a for loop :)
You can create an object lookup based on the first value of your array. Using this lookup, you can get the first key and then start adding value to your result. Once you add a value in the array, remove the value corresponding to that key, if the key has no element in its array delete its key. Continue this process as long as you have keys in your object lookup.
var vector = [["PROPRI", "PORVEC"],["AJATRN", "PROPRI"],["BASMON", "CALVI"],["GHICIA", "FOLELI"],["FOLELI", "BASMON"],["PORVEC", "GHICIA"]],
lookup = vector.reduce((r,a) => {
r[a[0]] = r[a[0]] || [];
r[a[0]].push(a);
return r;
}, {});
var current = Object.keys(lookup).sort()[0];
var sorted = [];
while(Object.keys(lookup).length > 0) {
if(lookup[current] && lookup[current].length) {
var first = lookup[current].shift();
sorted.push(first);
current = first[1];
} else {
delete lookup[current];
current = Object.keys(lookup).sort()[0];
}
}
console.log(sorted);

Split nested array into multiple arrays

I have a string that looks like this:
str = {1|2|3|4|5}{a|b|c|d|e}
I want to split it into multiple arrays. One containing all the first elements in each {}, one containing the second element, etc. Like this:
arr_0 = [1,a]
arr_1 = [2,b]
arr_2 = [3,c]
.....
The best I can come up with is:
var str_array = str.split(/}{/);
for(var i = 0; i < str_array.length; i++){
var str_row = str_array[i];
var str_row_array = str_row.split('|');
arr_0.push(str_row_array[0]);
arr_1.push(str_row_array[1]);
arr_2.push(str_row_array[2]);
arr_3.push(str_row_array[3]);
arr_4.push(str_row_array[4]);
}
Is there a better way to accomplish this?
Try the following:
var zip = function(xs, ys) {
var out = []
for (var i = 0; i < xs.length; i++) {
out[i] = [xs[i], ys[i]]
}
return out
}
var res = str
.split(/\{|\}/) // ['', '1|2|3|4|5', '', 'a|b|c|d|e', '']
.filter(Boolean) // ['1|2|3|4|5', 'a|b|c|d|e']
.map(function(x){return x.split('|')}) // [['1','2','3','4','5'], ['a','b','c','d','e']]
.reduce(zip)
/*^
[['1','a'],
['2','b'],
['3','c'],
['4','d'],
['5','e']]
*/
Solution
var str = '{1|2|3|4|5}{a|b|c|d|e}'.match(/[^{}]+/g).map(function(a) {
return a.match(/[^|]+/g);
}),
i,
result = {};
for (i = 0; i < str[0].length; i += 1) {
result["arr_" + i] = [+str[0][i], str[1][i]];
}
How it works
The first part, takes the string, and splits it into the two halves. The map will return an array after splitting them after the |. So str is left equal to:
[
[1,2,3,4,5],
['a', 'b', 'c', 'd', 'e']
]
The for loop will iterate over the [1,2,3,4,5] array and make the array with the appropriate values. The array's are stored in a object. The object we are using is called result. If you don't wish for it to be kept in result, read Other
Other
Because you can't make variable names from another variable, feel free to change result to window or maybe even this (I don't know if that'll work) You can also make this an array
Alternate
var str = '{1|2|3|4|5}{a|b|c|d|e}'.match(/[^{}]+/g).map(function(a) { return a.match(/[^|]+/g); }),
result = [];
for (var i = 0; i < str[0].length; i += 1) {
result[i] = [+str[0][i], str[1][i]];
}
This is very similar except will generate an Array containing arrays like the other answers,

Sort array by order according to another array

I have an object that is being returned from a database like this: [{id:1},{id:2},{id:3}]. I have another array which specified the order the first array should be sorted in, like this: [2,3,1].
I'm looking for a method or algorithm that can take in these two arrays and return [{id:2},{id:3},{id:1}]. Ideally it should be sort of efficient and not n squared.
If you want linear time, first build a hashtable from the first array and then pick items in order by looping the second one:
data = [{id:5},{id:2},{id:9}]
order = [9,5,2]
hash = {}
data.forEach(function(x) { hash[x.id] = x })
sorted = order.map(function(x) { return hash[x] })
document.write(JSON.stringify(sorted))
function sortArrayByOrderArray(arr, orderArray) {
return arr.sort(function(e1, e2) {
return orderArray.indexOf(e1.id) - orderArray.indexOf(e2.id);
});
}
console.log(sortArrayByOrderArray([{id:1},{id:2},{id:3}], [2,3,1]));
In your example, the objects are initially sorted by id, which makes the task pretty easy. But if this is not true in general, you can still sort the objects in linear time according to your array of id values.
The idea is to first make an index that maps each id value to its position, and then to insert each object in the desired position by looking up its id value in the index. This requires iterating over two arrays of length n, resulting in an overall runtime of O(n), or linear time. There is no asymptotically faster runtime because it takes linear time just to read the input array.
function objectsSortedBy(objects, keyName, sortedKeys) {
var n = objects.length,
index = new Array(n);
for (var i = 0; i < n; ++i) { // Get the position of each sorted key.
index[sortedKeys[i]] = i;
}
var sorted = new Array(n);
for (var i = 0; i < n; ++i) { // Look up each object key in the index.
sorted[index[objects[i][keyName]]] = objects[i];
}
return sorted;
}
var objects = [{id: 'Tweety', animal: 'bird'},
{id: 'Mickey', animal: 'mouse'},
{id: 'Sylvester', animal: 'cat'}],
sortedIds = ['Tweety', 'Mickey', 'Sylvester'];
var sortedObjects = objectsSortedBy(objects, 'id', sortedIds);
// Check the result.
for (var i = 0; i < sortedObjects.length; ++i) {
document.write('id: '+sortedObjects[i].id+', animal: '+sortedObjects[i].animal+'<br />');
}
To my understanding, sorting is not necessary; at least in your example, the desired resulting array can be generated in linear time as follows.
var Result;
for ( var i = 0; i < Input.length; i++ )
{
Result[i] = Input[Order[i]-1];
}
Here Result is the desired output, Input is your first array and Order the array containing the desired positions.
var objArray = [{id:1},{id:2},{id:3}];
var sortOrder = [2,3,1];
var newObjArray = [];
for (i in sortOrder) {
newObjArray.push(objArray[(sortOrder[i]) - 1])
};
Why not just create new array and push the value from second array in?? Correct me if i wrong
array1 = [];
array2 = [2,3,1];
for ( var i = 0; i < array2 .length; i++ )
{
array1.push({
id : array2[i]
})
}

How do I define an associative array?

I want to define what I understand is an associative array (or maybe an object) such that I have entries like the following:
"Bath" = [1,2,5,5,13,21]
"London" = [4,7,13,25]
I've tried the following:
var xref = new Object;
xref = [];
obj3 = {
offices: []
};
xref.push(obj3);
Then cycling through my data with
xref[name].offices.push(number);
But I get "TypeError: xref[name] is undefined". What am I doing wrong ?
Use an object like you do with obj3:
var xref = {};
xref.obj3 = obj3;
var name = 'obj3';
xref[name].offices.push(number);
var obj = {
arr : [],
}
var name = "vinoth";
obj.arr.push(name);
console.log(obj.arr.length);
console.log(obj.arr[0]);
obj.prop = "Vijay";
console.log(obj.prop);
You can use an object literal.
I realised that all I really wanted was a 2 dimensional array with the first dimension being the key (ie. "BATH", "LONDON") and the second being the list of cross-references (ie. 1,2,5,5,13,21) - so I don't need to understand the Object route yet ! The other suggestions may well work and be "purer" but the 2 dimensional array is easier for my old-fashioned brain to work with.
So I did the following:
var xref = [];
// go through source arrays
for (i = 0; i < offices.length; i++) {
for (j = 0; j < offices[i].rel.length; j++) {
// Check if town already exists, if not create array, then push index
if (xref[offices[i].rel[j].town] === undefined) {
xref[offices[i].rel[j].town] = [];
alert('undefined so created '+offices[i].rel[j].town);
};
xref[offices[i].rel[j].town].push(i); // Add index to town list
};
};
I believe from reading other posts that I would have problems if any of the 'offices[i].rel[j].town' were set to undefined but the data doesn't have this possibility.
Now I can access a cross-reference list by doing something like:
townlist = "";
for (i = 0; i < xref["BATH"].length; i++) {
townlist += offices[xref["BATH"][i]].name+' ';
};
alert(townlist);

How can i delete something out of an array?

My problem is that i have to delete something out of an array. I found out how to delete something out of a listbox. But the problem is that the listbox is filled by an array. So if I don't delete the value (I deleted out of the listbox) out of the array. The value keeps coming back when you add a new item. BTW: I am new to php and javascript.
My code is:
function removeItem(veldnaam){
var geselecteerd = document.getElementById("lst"+veldnaam).selectedIndex;
var nieuweArray;
alert(geselecteerd);
alert(document.getElementById(veldnaam+'hidden').value);
For (var i = 0, i<= arr.lenght, i++) {
If (i= geselecteerd){
nieuweArray = arr.splice(i,1);
document.getElementById(veldnaam+'hidden').value = arr;
}}
document.getElementById("lst"+veldnaam).remove(geselecteerd);
}
Use the delete operator. I'm assuming you are using objects as associative arrays.
var arr = {
"hello": "world",
"foo": "bar"
}
delete arr["foo"]; // Removes item with key "foo"
You can delete elements in an array using the delete command. But it will just set the value to undefined.
var arr = ['h', 'e', 'l', 'l', 'o'];
delete arr[2];
arr => ['h', 'e', undefined, 'l', 'o'];
So it will not remove the item, and make a shorter array, the array will still have 5 elements (0 to 4), but the value has been deleted.
In the case of "associative" arrays, or objects: The property will get erased and it will no longer exist.
var obj = { 'first':'h', 'second':'e', 'third':'l'};
delete obj['first'];
obj => { 'second':'e', 'third':'l'};
Add the following code somewhere
// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
and call it like this:
// Remove the second item from the array
array.remove(1);
// Remove the second-to-last item from the array
array.remove(-2);
// Remove the second and third items from the array
array.remove(1,2);
// Remove the last and second-to-last items from the array
array.remove(-2,-1);
Article containing the code above and explanation: http://ejohn.org/blog/javascript-array-remove/
var geselecteerd = document.getElementById("lst"+veldnaam).selectedIndex;
var nieuweArray;
var teller = 0;
var oudeArray=document.getElementById(veldnaam+'hidden').value;
var tmpArr="";
nieuweArray=oudeArray.split(":");
for (i = 0; i<nieuweArray.length; i++){
if (!(i==geselecteerd)){
tmpArr = tmpArr+nieuweArray[i]+":";}
teller++;
}
tmpArr = tmpArr + ":";
tmpArr = tmpArr.replace("::","");
document.getElementById(veldnaam+'hidden').value = tmpArr;
document.getElementById("lst"+veldnaam).remove(geselecteerd);
}
This is my solution and it worked. Thanks for your help.

Categories