how can I dynamically access indexes in an array? - javascript

I have a rootArray with some nested arrays, it could be any depth.
I want to dynamically access a certain inner array, defined by a list of indexes, to push new content there.
so for example, if the list of index is
currentFocusedArray = [1,2]
i want to...
rootArray[1][2].push('new content')
dynamically, not hardwired.
Maybe this is a case of the trees not letting me see the forest or maybe I am on a dead end.
I am just making a note taking simple app, with react, very simple yet.
https://codesandbox.io/embed/quirky-gauss-09i1h
Any advice is welcome!
Hopefully I didnt waste your time. Thanks in advance.

You can write find array to get array based on your focus array.
Use array method reduce to find node from an array of indexes
var updateNode = focus.reduce((node,index) => node && node[index], notes);
updateNode && updateNode.push("new content");

You can make it with a for loop.
let myArray = rootArray
for(let i = 0; i < currentFocusedArray.length; i++){
myArray = myArray[currentFocusedArray[i]]
}
After this, you will have myArray reference the deep nested value of rootArray.
let rootArray = {
"1": {
"2": []
}
}
let currentFocusedArray = [1, 2]
let myArray = rootArray
for(let i = 0; i < currentFocusedArray.length; i++){
myArray = myArray[currentFocusedArray[i]]
}
myArray.push("new content")
console.log(myArray)

You could use reduce to create such function that will set nested array element on any level.
const rootArray = []
function set(arr, index, value) {
index.reduce((r, e, i, a) => {
if (!r[e]) {
if (a[i + 1]) r[e] = []
} else if (!Array.isArray(r[e])) {
if (a[i + 1]) {
r[e] = [r[e]]
}
}
if (!a[i + 1]) {
if (Array.isArray(r)) {
r[e] = value
}
}
return r[e]
}, arr)
}
set(rootArray, [1, 2], 'foo');
set(rootArray, [1, 1, 2], 'bar');
set(rootArray, [1, 2, 2], 'baz');
console.log(JSON.stringify(rootArray))

Related

JavaScript array: is there a method that is a cross between splice and filter?

I have an array of objects, and want to:
Remove certain objects from the array
Treat the removed objects in a second step
I don't know in advance where these objects are. To recognize them, I need to use a function that queries their properties. It makes sense to retrieve the removed objects in a second array.
I had hoped to find a native method like filter or splice that would do this. Here's what I've come up with as a solution:
if (!Array.prototype.cherrypick) {
Array.prototype.cherrypick = function(fn) {
let basket = []
let ii = this.length
let item
for ( ; ii-- ; ) {
item = this[ii]
if (fn(item)) {
basket.unshift(item)
this.splice(ii, 1)
}
}
return basket
}
}
Have I missed something? Is there a native method that does this already? Is my solution unsound in some way?
Have I missed something? Is there a native method that does this already?
No, most native utility methods try not to mutate the array and instead return a new one.
Is my solution unsound in some way?
Using splice and unshift repeatedly like you do is very inefficient. Better write
if (typeof Array.prototype.cherrypick == "function")
console.warn("something already defines Array#cherrypick!");
Array.prototype.cherrypick = function(predicate) {
let removed = [];
for (let i=0, j=0; i<this.length; i++) {
const item = this[i];
if (fn(item)) {
removed.push(item);
} else {
this[j++] = item; // keep in array, but at new position
}
}
this.length = j; // removes rest
return removed;
};
Methods such as Array.filter() returns a new array instead of changing the original array.
You can create a partition method using Array.reduce() that will return two arrays - those that passed the predicate, and those that failed:
const partition = (predicate, arr) =>
arr.reduce((r, o) => {
r[+!!predicate(o)].push(o);
return r;
}, [[], []]);
const arr = [4, 8, 3, 10, 12];
const result = partition(n => n > 5, arr);
console.log(result);
And you can use the partition logic with Array.splice() to create the cherrypick method:
if (!Array.prototype.cherrypick) {
Array.prototype.cherrypick = function(predicate) {
const [removedItems, items] = arr.reduce((r, o) => {
r[+!!predicate(o)].push(o);
return r;
}, [[], []]);
this.splice(0, arr.length, items);
return removedItems;
}
}
const arr = [4, 8, 3, 10, 12];
const removed = arr.cherrypick(n => n > 5);
console.log('arr ', arr);
console.log('removed ', removed);
Just filter twice:
const picked = array.filter(fn);
array = array.filter((el, i, a) => !fn(el, i, a));
Use reduce as follows :
array = [1,2,3,4,5,6,7];
fn = n => n % 3 == 0;
[array, picked] = array.reduce ( (r, el) => (r[+fn(el)].push (el), r), [[], []] )
Do you want something like this?
const basket = ['apple', 'banana', 'car'];
const filterMapBasket = basket
.filter(item => item !== 'car')
.map(item => {return { name: item }});
This will result the initial basket array of strings to be filtered and transformed to an array of objects.
This will alter the source array in place removing items meeting some test, and return those items...
Array.prototype.removeIf = function(fn) {
let i = this.length;
let removed = [];
while (i--) {
if (fn(this[i], i)) {
removed.push(...this.splice(i, 1));
}
}
return removed;
};
let a = [0,1,2,3,4,5];
let removed = a.removeIf(i => i%2);
console.log(a);
console.log(removed);

Shifting rows and columns in 2D arrays - Javascript

I have a situation as such:
var array = [
[1,2,3],
[4,5,6],
[7,8,9]
]
And I am trying to create a function that shifts either a row or a column so the result would be:
shiftRow(array, 1)
[
[3,1,2],
[4,5,6],
[7,8,9]
]
shiftColumn(array,1)
[
[7,2,3],
[1,5,6],
[4,8,9]
]
I want the first number to be the last number then continue from there in any instance. I have tried several nested for loops, and I'm quite stuck at figuring this out. Keep in mind I have only been coding for a few months though.
This is what I have so far. It gives me an undefined error at the end and it is moving it the wrong way.
function shiftRow(arr) {
var temp = arr
for(var i = 0; i < temp.length; i++) {
for(var j = 0; j < temp[i].length; j++) {
temp[i][j] = temp[i][j+1]
}
}
return temp;
}
The previous answers looks ok, but lacks one major thing when dealing with array indexes ; validation checks.
You do not want to try to access non-existent array indexes. Therefore, I created a small class to shift your array as needed, with validation. This will throw an Error if either the row or column index is invalid.
class ArrayShifter {
static showArray(array) {
// console.log("Array : ", array);
console.log('------');
for (const [index, elem] of array.entries()) {
console.log(''+elem);
}
}
static validateRowIndex(array, rowIndex) {
if (!isArray(array) || !isInt(rowIndex) || rowIndex <= 0 || rowIndex > array.length) {
throw new Error('The row index is wrong');
}
}
static validateColumnIndex(array, columnIndex) {
if (!isArray(array) || !isInt(columnIndex) || columnIndex <= 0 || columnIndex > array[0].length) {
throw new Error('The column index is wrong');
}
}
static shiftRow(array, rowIndex) {
ArrayShifter.validateRowIndex(array, rowIndex);
array[rowIndex - 1].unshift(array[rowIndex - 1].pop());
return array;
}
static shiftColumn(array, columnIndex) {
ArrayShifter.validateColumnIndex(array, columnIndex);
let prev = array[array.length - 1][columnIndex - 1];
for (const elem of array) {
let tmp = elem[columnIndex - 1];
elem[columnIndex - 1] = prev;
prev = tmp;
}
return array;
}
}
let sourceArray1 = [
[1,2,3],
[4,5,6],
[7,8,9],
];
let sourceArray2 = [
[1,2,3],
[4,5,6],
[7,8,9],
];
let controlArrayShiftRow = [
[3,1,2],
[4,5,6],
[7,8,9],
];
let controlArrayColumnRow = [
[7,2,3],
[1,5,6],
[4,8,9],
];
// arrayShifter.showArray(sourceArray1);
console.log(`Shift row test is ${areArraysEqual(controlArrayShiftRow, ArrayShifter.shiftRow(sourceArray1, 1))}.`);
// arrayShifter.showArray(sourceArray2);
console.log(`Shift column test is ${areArraysEqual(controlArrayColumnRow, ArrayShifter.shiftColumn(sourceArray2, 1))}.`);
//-------------------- Unimportant js functions --------------------
function isArray(arr) {
if (Object.prototype.toString.call([]) === '[object Array]') { //Make sure an array has a class attribute of [object Array]
//Test passed, now check if is an Array
return Array.isArray(arr) || (typeof arr === 'object' && Object.prototype.toString.call(arr) === '[object Array]');
}
else {
throw new Exception('toString message changed for Object Array'); //Make sure the 'toString' output won't change in the futur (cf. http://stackoverflow.com/a/8365215)
}
}
function isInt(n) {
return typeof n === 'number' && parseFloat(n) === parseInt(n, 10) && !isNaN(n);
}
function areArraysEqual(a1, a2) {
return JSON.stringify(a1) == JSON.stringify(a2);
}
The working code can be seen in this codepen.
For row shift you can use Array#unshift and Array#pop methods. And for shifting the column use a Array#forEach method with a temp variable.
var array = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
],
array1 = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
function shiftRow(arr, row) {
arr[row - 1].unshift(arr[row - 1].pop());
return arr;
}
function shiftCol(arr, col) {
var prev = arr[arr.length - 1][col-1];
arr.forEach(function(v) {
var t = v[col - 1];
v[col - 1] = prev;
prev = t;
})
return arr;
}
console.log(shiftRow(array, 1))
console.log(shiftCol(array1, 1))
First, you have to pass two arguments: the array, and the row/column you want to shift. And remember that arrays are zero-based, not 1. So in your example, if you want to shit the first row, you need to pass 0, not 1.
Second, since you want to put the last element at the front, and push others down, you need to loop, for shiftRow, from back to front. Here's a solution. Feel free to improve on it.
function shiftRow(arr, row) {
var temp = arr[row];
var j=temp.length-1;
var x=temp[j];
for(var i = j; i > 0; i--) {
temp[i]=temp[i-1];
}
temp[0]=x;
arr[row]=temp;
}
As you can see it works only on the row you want to shift, and starts from the end, working its way to the front. Before the loop I save the last element (which will be overwritten) and put that in the first slot at the end of the loop.
Given this question :
Transposing a javascript array efficiently
It is sufficient to implement only shiftRow and transpose before and after it if we want to achieve shiftCol
function shiftRow(array,n)
{
let retVal=[[]];
for(i=0;i<array.length;i++)
{
if (i==n)
retVal[i]= array[i].slice(1,array.length).concat(array[i][0]);
else
retVal[i]=array[i];
}
return retVal;
}

Iterative solution for flattening n-th nested arrays in Javascript

Can anyone show me an iterative solution for the following problem? I solved it recursively but struggled with an iterative solution. (Facebook Technical Interview Question)
Input: [1, {a: 2}, [3], [[4, 5], 6], 7]
Output: [1, {a: 2}, 3, 4, 5, 6, 7]
Solution must work with n-th nested array elements (i.e. it must still work if someone modifies the array values/placement in the example above)
Recursive solution:
var flatten = function(input) {
var result = [];
input.forEach(function(element) {
result = result.concat(Array.isArray(element) ? flatten(element) : element);
});
return result;
}
Here is one way:
var input = [1, {a: 2}, [3], [[4, 5], 6], 7];
function flatten(input) {
var i, placeHolder = [input], lastIndex = [-1], out = [];
while (placeHolder.length) {
input = placeHolder.pop();
i = lastIndex.pop() + 1;
for (; i < input.length; ++i) {
if (Array.isArray(input[i])) {
placeHolder.push(input);
lastIndex.push(i);
input = input[i];
i = -1;
} else out.push(input[i]);
}
}
return out;
}
flatten(input);
Explanation: If iterating over a nested structure, you just have to remember where you were before by saving the current array and position before moving into the nested array (this is usually taken care of via the stack for recursive solutions).
Note: If you reuse the arrays placeHolder and lastIndex you won't need to keep recreating them every time. Perhaps something like this:
var flatten = function(){
var placeHolder = [], lastIndex = [];
placeHolder.count = 0;
lastIndex.count = 0;
return function flatten(input) {
var i, out = [];
placeHolder[0] = input; placeHolder.count = 1;
lastIndex[0] = -1; lastIndex.count = 1;
while (placeHolder.count) {
input = placeHolder[--placeHolder.count];
i = lastIndex[--lastIndex.count] + 1;
for (; i < input.length; ++i) {
if (Array.isArray(input[i])) {
placeHolder[placeHolder.count++] = input;
lastIndex[lastIndex.count++] = i;
input = input[i];
i = -1;
} else out.push(input[i]);
}
}
return out;
}
}();
This is even faster again (for flat iteration that is), and less garbage collector issues calling it many times. The speed is very close to that of recursive function calling in Chrome, and many times faster than recursion in FireFox and IE.
I recreated Tomalak's tests here since the old jsPerf is broken for editing: https://jsperf.com/iterative-array-flatten-2
How about this?
inp = [1, {a: 2}, [3], [[4, 5], 6], 7]
out = inp;
while(out.some(Array.isArray))
out = [].concat.apply([], out);
document.write(JSON.stringify(out));
Works, but not recommended:
var flatten = function(input) {
return eval("[" + JSON.stringify(input).
replace(/\[/g,"").replace(/\]/g,"") + "]");
}
Here's a solution that flattens in place.
function flatten(arr) {
var i = 0;
if (!Array.isArray(arr)) {
/* return non-array inputs immediately to avoid errors */
return arr;
}
while (i < arr.length) {
if (Array.isArray(arr[i])) {
arr.splice(i, 1, ...arr[i]);
} else {
i++;
}
}
return arr;
}
This solution iterates through the array, flattening each element one level of nesting at a time until it cannot be flattened any more.
function flatten(array){
for(var i=0;i<array.length;i++)
if(Array.isArray(array[i]))
array.splice.apply(array,[i,1].concat(array[i--]));
return array;
}
This in-place solution is faster than Lupe's, now that I've removed all of the inner curly brackets (I inlined the i-- in the concat parameter to do that).
A different iterative algorithm:
function flatten2(input) {
var output = [];
var todo = [input];
var current;
var head;
while(todo.length) {
var current = todo.shift();
if(Array.isArray(current)) {
current = current.slice();
head = current.shift();
if(current.length) {
todo.unshift(current)
}
todo.unshift(head);
} else {
output.push(current);
}
}
return output;
}
Put all elements on a stack.
While the stack is not empty, remove the first element.
If that element is a scalar, add it to the output.
If that element is an array, split it into head (first element) and tail (remaining elements) and add both to the stack.
As Tomalak's JSPerf shows, this is pretty slow.
JSBin
A fairly concise, readable algorithm:
function flatten(input) {
var output = [];
var todo = [input];
var current;
while(todo.length) {
var current = todo.shift();
if(Array.isArray(current)) {
todo.unshift.apply(todo, current)
} else {
output.push(current);
}
}
return output;
}
This version performs better than my other answer, but is still significantly slower than James Wilkins' answer.
JSBin
Tomalak's JSPerf
Here are two approaches, recursive and iterative and their comparison to Array.flat.
Maybe it'll help someone
const arrayToFlatten = [[1], [2, [3]], null, [[{}]], undefined];
// takes an array and flattens it recursively, default depth is 1 (just like Array.flat())
function flattenRecursive(arr, depth = 1) {
let myArray = [];
if (depth === 0){ // if you've reached the depth don't continue
myArray = arr;
} else if(!Array.isArray(arr)) { // add item to array if not an array
myArray.push(arr);
} else { // flatten each item in the array then concatenate
arr.forEach(item => {
const someNewArray = flattenRecursive(item, depth - 1);
myArray = myArray.concat(someNewArray);
});
}
return myArray;
}
// takes an array and flattens it using a loop, default depth is 1 (just like Array.flat())
function flattenIterative(arr, depth = 1) {
let result = arr;
// if an element is an array
while(result.some(Array.isArray) && depth) {
// flatten the array by one level by concating an empty array and result using apply
result = [].concat.apply([], result);
depth--; // track depth
}
return result;
}
console.log(arrayToFlatten.flat(2)); // ES^
console.log(flattenRecursive(arrayToFlatten, 2));
console.log(flattenIterative(arrayToFlatten, 2));
Here's my solution to this:
function flattenList(A) {
let result = []
for (let i=0; i < A.length; i++) {
if (typeof A[i] == "object"){
let item = reduceArray(A[i])
result.push(...item)
}else {
result.push(A[i])
}
}
return result
}
function reduceArray(arr){
while(arr.some(Array.isArray)) {
let item = arr.find(Array.isArray)
let index = arr.indexOf(item)
arr[index] = item[0]
}
return arr
}
Not sure if the "stack" approach was used properly in previous answers. I think it could be simpler, like this:
function flatten(arr) {
const result = [];
const stack = [arr];
while (stack.length) {
const curr = stack.pop();
if (Array.isArray(curr)) {
for (let i = curr.length - 1; i >= 0; i--) {
stack.push(curr[i]);
}
} else {
result.push(curr);
}
}
return result;
}
Not sure why the other answers are so complicated, this can easily be achieved by looping through the array and flattening each entry until it's no longer an array.
const flatten = (arr) => {
for (let i = 0; i < arr.length; i++) {
while (Array.isArray(arr[i])) {
arr.splice(i, 1, ...arr[i]);
}
}
return arr;
}

Count unique elements in array without sorting

In JavaScript the following will find the number of elements in the array. Assuming there to be a minimum of one element in the array
arr = ["jam", "beef", "cream", "jam"]
arr.sort();
var count = 1;
var results = "";
for (var i = 0; i < arr.length; i++)
{
if (arr[i] == arr[i+1])
{
count +=1;
}
else
{
results += arr[i] + " --> " + count + " times\n" ;
count=1;
}
}
Is it possible to do this without using sort() or without mutating the array in any way? I would imagine that the array would have to be re-created and then sort could be done on the newly created array, but I want to know what's the best way without sorting.
And yes, I'm an artist, not a programmer, your honour.
The fast way to do this is with a new Set() object.
Sets are awesome and we should use them more often. They are fast, and supported by Chrome, Firefox, Microsoft Edge, and node.js.
— What is faster Set or Object? by Andrei Kashcha
The items in a Set will always be unique, as it only keeps one copy of each value you put in. Here's a function that uses this property:
function countUnique(iterable) {
return new Set(iterable).size;
}
console.log(countUnique('banana')); //=> 3
console.log(countUnique([5,6,5,6])); //=> 2
console.log(countUnique([window, document, window])); //=> 2
This can be used to count the items in any iterable (including an Array, String, TypedArray, and arguments object).
A quick way to do this is to copy the unique elements into an Object.
var counts = {};
for (var i = 0; i < arr.length; i++) {
counts[arr[i]] = 1 + (counts[arr[i]] || 0);
}
When this loop is complete the counts object will have the count of each distinct element of the array.
Why not something like:
var arr = ["jam", "beef", "cream", "jam"]
var uniqs = arr.reduce((acc, val) => {
acc[val] = acc[val] === undefined ? 1 : acc[val] += 1;
return acc;
}, {});
console.log(uniqs)
Pure Javascript, runs in O(n). Doesn't consume much space either unless your number of unique values equals number of elements (all the elements are unique).
Same as this solution, but less code.
let counts = {};
arr.forEach(el => counts[el] = 1 + (counts[el] || 0))
This expression gives you all the unique elements in the array without mutating it:
arr.filter(function(v,i) { return i==arr.lastIndexOf(v); })
You can chain it with this expression to build your string of results without sorting:
.forEach(function(v) {
results+=v+" --> " + arr.filter(function(w){return w==v;}).length + " times\n";
});
In the first case the filter takes only includes the last of each specific element; in the second case the filter includes all the elements of that type, and .length gives the count.
This answer is for Beginners. Try this method you can solve this problem easily. You can find a full lesson for reduce, filter, map functions from This link.
const user = [1, 2, 2, 4, 8, 3, 3, 6, 5, 4, 8, 8];
const output = user.reduce(function (acc, curr) {
if (acc[curr]) {
acc[curr] = ++acc[curr];
} else {
acc[curr] = 1;
}
return acc;
}, {});
console.log(output);
function reomveDuplicates(array){
var newarray = array.filter( (value, key)=>{
return array.indexOf(value) == key
});
console.log("newarray", newarray);
}
reomveDuplicates([1,2,5,2,1,8]);
Using hash Map with the time complexity O(n)
function reomveDuplicates(array){
var obj ={};
let res=[];
for( arg of array){
obj[arg] = true;
}
console.log(Object.keys(obj));
for(key in obj){
res.push(Number(key)); // Only if you want in Number
}
console.log(res);
}
reomveDuplicates([1,2,5,2,1,8]);
In a modern, extensible and easy-to-read approach, here's one using iter-ops library:
import {pipe, distinct, count} from 'iter-ops';
const arr = ['jam', 'beef', 'cream', 'jam'];
const count = pipe(arr, distinct(), count()).first;
console.log(count); //=> 3
function check(arr) {
var count = 0;
for (var ele of arr) {
if (typeof arr[ele] !== typeof (arr[ele+1])) {
count++;
} else {
("I don't know");
}
}
return count;
}

Reordering arrays

Say, I have an array that looks like this:
var playlist = [
{artist:"Herbie Hancock", title:"Thrust"},
{artist:"Lalo Schifrin", title:"Shifting Gears"},
{artist:"Faze-O", title:"Riding High"}
];
How can I move an element to another position?
I want to move for example, {artist:"Lalo Schifrin", title:"Shifting Gears"} to the end.
I tried using splice, like this:
var tmp = playlist.splice(2,1);
playlist.splice(2,0,tmp);
But it doesn't work.
The syntax of Array.splice is:
yourArray.splice(index, howmany, element1, /*.....,*/ elementX);
Where:
index is the position in the array you want to start removing elements from
howmany is how many elements you want to remove from index
element1, ..., elementX are elements you want inserted from position index.
This means that splice() can be used to remove elements, add elements, or replace elements in an array, depending on the arguments you pass.
Note that it returns an array of the removed elements.
Something nice and generic would be:
Array.prototype.move = function (from, to) {
this.splice(to, 0, this.splice(from, 1)[0]);
};
Then just use:
var ar = [1,2,3,4,5];
ar.move(0,3);
alert(ar) // 2,3,4,1,5
Diagram:
If you know the indexes you could easily swap the elements, with a simple function like this:
function swapElement(array, indexA, indexB) {
var tmp = array[indexA];
array[indexA] = array[indexB];
array[indexB] = tmp;
}
swapElement(playlist, 1, 2);
// [{"artist":"Herbie Hancock","title":"Thrust"},
// {"artist":"Faze-O","title":"Riding High"},
// {"artist":"Lalo Schifrin","title":"Shifting Gears"}]
Array indexes are just properties of the array object, so you can swap its values.
With ES6 you can do something like this:
const swapPositions = (array, a ,b) => {
[array[a], array[b]] = [array[b], array[a]]
}
let array = [1,2,3,4,5];
swapPositions(array,0,1);
/// => [2, 1, 3, 4, 5]
Here is an immutable version for those who are interested:
function immutableMove(arr, from, to) {
return arr.reduce((prev, current, idx, self) => {
if (from === to) {
prev.push(current);
}
if (idx === from) {
return prev;
}
if (from < to) {
prev.push(current);
}
if (idx === to) {
prev.push(self[from]);
}
if (from > to) {
prev.push(current);
}
return prev;
}, []);
}
You could always use the sort method, if you don't know where the record is at present:
playlist.sort(function (a, b) {
return a.artist == "Lalo Schifrin"
? 1 // Move it down the list
: 0; // Keep it the same
});
Change 2 to 1 as the first parameter in the splice call when removing the element:
var tmp = playlist.splice(1, 1);
playlist.splice(2, 0, tmp[0]);
Immutable version, no side effects (doesn’t mutate original array):
const testArr = [1, 2, 3, 4, 5];
function move(from, to, arr) {
const newArr = [...arr];
const item = newArr.splice(from, 1)[0];
newArr.splice(to, 0, item);
return newArr;
}
console.log(move(3, 1, testArr));
// [1, 4, 2, 3, 5]
codepen: https://codepen.io/mliq/pen/KKNyJZr
EDIT: Please check out Andy's answer as his answer came first and this is solely an extension of his
I know this is an old question, but I think it's worth it to include Array.prototype.sort().
Here's an example from MDN along with the link
var numbers = [4, 2, 5, 1, 3];
numbers.sort(function(a, b) {
return a - b;
});
console.log(numbers);
// [1, 2, 3, 4, 5]
Luckily it doesn't only work with numbers:
arr.sort([compareFunction])
compareFunction
Specifies a function that defines the sort order. If omitted, the array is sorted according to each character's Unicode code point value, according to the string conversion of each element.
I noticed that you're ordering them by first name:
let playlist = [
{artist:"Herbie Hancock", title:"Thrust"},
{artist:"Lalo Schifrin", title:"Shifting Gears"},
{artist:"Faze-O", title:"Riding High"}
];
// sort by name
playlist.sort((a, b) => {
if(a.artist < b.artist) { return -1; }
if(a.artist > b.artist) { return 1; }
// else names must be equal
return 0;
});
note that if you wanted to order them by last name you would have to either have a key for both first_name & last_name or do some regex magic, which I can't do XD
Hope that helps :)
Try this:
playlist = playlist.concat(playlist.splice(1, 1));
If you only ever want to move one item from an arbitrary position to the end of the array, this should work:
function toEnd(list, position) {
list.push(list.splice(position, 1));
return list;
}
If you want to move multiple items from some arbitrary position to the end, you can do:
function toEnd(list, from, count) {
list.push.apply(list, list.splice(from, count));
return list;
}
If you want to move multiple items from some arbitrary position to some arbitrary position, try:
function move(list, from, count, to) {
var args = [from > to ? to : to - count, 0];
args.push.apply(args, list.splice(from, count));
list.splice.apply(list, args);
return list;
}
Time complexity of all answers is O(n^2) because had used twice spice. But O(n/2) is possible.
Most Perfomance Solution:
Array with n elements,
x is to, y is from
should be n >x && n > y
time complexity should be |y - x|. So its is number of elements that is between from and to.
bestcase: O(1); //ex: from:4 to:5
average : O(n/2)
worthcase : O(n) //ex: from:0 to:n
function reOrder(from,to,arr) {
if(from == to || from < 0 || to < 0 ) { return arr};
var moveNumber = arr[from];
if(from < to) {
for(var i =from; i< to; i++){
arr[i] = arr[i+1]
}
}
else{
for(var i = from; i > to; i--){
arr[i] = arr[i-1];
}
}
arr[to] = moveNumber;
return arr;
}
var arr = [0,1,2,3,4,5,6,7,8,9,10,11,12,13];
console.log(reOrder(3,7,arr));
As a simple mutable solution you can call splice twice in a row:
playlist.splice(playlist.length - 1, 1, ...playlist.splice(INDEX_TO_MOVE, 1))
On the other hand, a simple inmutable solution could use slice since this method returns a copy of a section from the original array without changing it:
const copy = [...playlist.slice(0, INDEX_TO_MOVE - 1), ...playlist.slice(INDEX_TO_MOVE), ...playlist.slice(INDEX_TO_MOVE - 1, INDEX_TO_MOVE)]
I came here looking for a rearranging complete array, I want something like I did below, but found most of the answers for moving only one element from position A to position B.
Hope my answer will help someone here
function reArrangeArray(firstIndex=0,arr){
var a = [];
var b = []
for(let i = 0; i<= (arr.length-1); i++){
if(i<firstIndex){
a.push(arr[i])
}else{
b.push(arr[i])
}
}
return b.concat(a)
}
const arrayToRearrange = [{name: 'A'},{name: 'B'},{name: 'C'},{name: 'D'},{name: 'E'}];
reArrangeArray(2,arrayToRearrange)
// Output
// [
// { name: 'C' },
// { name: 'D' },
// { name: 'E' },
// { name: 'A' },
// { name: 'B' }
// ]
Reorder its work This Way
var tmpOrder = playlist[oldIndex];
playlist.splice(oldIndex, 1);
playlist.splice(newIndex, 0, tmpOrder);
I hope this will work

Categories

Resources