Find the lastIndexOf() an object with a key in array of objects - javascript

I'm looking for a way to find the last index of an object in Javascript from a point in an array. For example:
array.lastIndexOf(object.key, start);
So far, I haven't found a good solution for this problem. I could splice the array from the 'start' point, reverse it, and then search the sliced array for the key value, but this seems like an inefficient solution to me.
EDIT:
To illustrate the problem a little more, I'm posting the code that I used in the end to solve the problem. Essentially; what I did was I used While to loop through the previous values in the array.
getLastValue = (index) => {
const arr = [
{'d':'01-02-2017','v':'123'},
{'d':'02-02-2017'},
{'d':'04-02-2017'},
{'d':'05-02-2017','v':'456'},
...
];
let lastValue;
while (arr[index] && !arr[index].v) {
index--;
}
lastValue = arr[index];
return lastValue;
}

Personally, I wouldn't choose either solution. Here is why:
LastIndexOf:
The problem lies in the comparing of elements while searching through the array. It does compare the elements using strict equality. Therefore comparing objects will always fail, except they are the same. In OP case they are different.
Slice & reverse one-liner #adeneo
Given an array of three elements [{key: A},{key: B},{key: C}] and the lookup for the last index of key = D will give you an index of 3. This is wrong as the last index should be -1 (Not found)
Looping through the array
While this is not necessarily wrong, looping through the whole array to find the element isn't the most concise way to do it. It's efficient yes, but readability can suffer from it. If I had to choose one, I'd probably choose this one. If readability / simplicity is your friend, then below is yet one more solution.
A simple solution
We can make lastIndexOf work, we just need to make the value comparable (strict equality conform). Or simply put: we need to map the objects to a single property that we want to find the last index of using javascript's native implementation.
const arr = [ { key: "a" }, { key: "b" }, { key: "c" }, { key: "e" }, { key: "e" }, { key: "f" } ];
arr.map(el => el.key).lastIndexOf("e"); //4
arr.map(el => el.key).lastIndexOf("d"); //-1
// Better:
const arrKeys = arr.map(el => el.key);
arrKeys.lastIndexOf("c"); //2
arrKeys.lastIndexOf("b"); //1
A fast solution
Simple backwards lookup (as concise and as fast as possible). Note the -1 return instead of null/undefined.
const arr = [ { key: "a" }, { key: "b" }, { key: "c" }, { key: "e" }, { key: "e" }, { key: "f" } ];
const lastIndexOf = (array, key) => {
for(let i = array.length - 1; i >= 0; i--){
if(array[i].key === key)
return i;
}
return -1;
};
lastIndexOf(arr, "e"); //4
lastIndexOf(arr, "x"); //-1

With ES2015 and findIndex you can pass a callback to look for an objects key.
If you make a copy of the array, and reverse it, you can find the last one by subtracting that index from the total length (and 1, as arrays are zero based)
It's not very efficient, but it's one line, and works well for normally sized arrays i.e. not a million indices
var idx = arr.length - 1 - arr.slice().reverse().findIndex( (o) => o.key == 'key' );
var arr = [{key : 'not'}, {key : 'not'}, {key : 'key'}, {key : 'not'}];
var idx = arr.length - 1 - arr.slice().reverse().findIndex( (o) => o.key == 'key' ); // 2
console.log(idx)
A more efficient approach would be to iterate backwards until you find the object you're looking for, and break the loop
var arr = [{key: 'not'}, {key: 'not'}, {key: 'key'}, {key: 'not'}];
var idx = (function(key, i) {
for (i; i--;) {
if (Object.values(arr[i]).indexOf(key) !== -1) {
return i;
break;
}
} return -1;
})('key', arr.length);
console.log(idx)

I think you want something like below:
var arr = [ { key: "a" }, { key: "b" }, { key: "c" }, { key: "e" }, { key: "e" }, { key: "f" } ];
console.log(lastIndexOf("e", 2));
function lastIndexOf(keyValue, start) {
for (var i = arr.length - 1; i >= start; i--) {
if (arr[i].key === keyValue) {
return i;
}
}
return null;
}

You can do this:
reverse your array: let newArr = arr.reverse()
use findIndex: newArr.findIndex(obj => obj.d == "your String")

i used sample code, like this:
//find last index in object array
const lastIndexOf = arr.reduce((acc,cur,idx)=>cur.key==xxx?idx:acc,-1)
//find last index of object in object array
const lastIndexOfObject = arr.reduce((acc,cur,idx)=>cur.key==xxx?cur:acc,undefined)

Just try to find last index in the whole massive and compare it to start
let ind = array.lastIndexOf(object.key);
if (ind > start) {return}

let a = [
{prop1:"abc",prop2:"incomplete"},
{prop1:"bnmb",prop2:"completed"},
{prop1:"bnmb",prop2:"prajapati"},
{prop1:"zxvz",prop2:"testAJ"},
{prop1:"last",prop2:"completed"},
{prop1:"last",prop2:"incomplete"},
{prop1:"last",prop2:"incomplete11"},
{prop1:"last",prop2:"incomplete"},
{prop1:"last",prop2:"incomplete"},
{prop1:"last",prop2:"incompleteness"},
];
let findLastduplicateObjectIndex = a.map(el => el.prop2).lastIndexOf("incomplete");

Related

Get n number of consecutive elements of an array

Given an array and an (variable) integer n, I want to create a new array comprising n number of consecutive elements of the array. I have it if n = 2 but I can't figure how to enable variable n:
var arr = ["first", "second", "third", "fourth", "fifth", "sixth" ];
var int = 3;
function consecEls(array, int) {
newArr = arr.map(function(val, ix, arr) {
var next = ix+1; // this works if I only needed firstsecond, secondthird, etc. but I need arbitrary # of consecutive els
// var next = ... ? ... next n els
var els = arr.slice(arr[ix], int); // or slice(ix, int) ... both return ["first", "second", "third"]
if (next !== arr.length) {
return val + arr[next];
}
else { return val; }
}) // forEach
return newArr;
}
consecEls(arr, int);
Any insight is much appreciated,
================================================
As I mentioned in the comments below, here's my very slightly modified version of #gyre's solution:
var arr = ["first", "second", "third", "fourth", "fifth", "sixth" ];
function map(array, groupSize, callback, context) {
var i = 0;
var result = [];
while (i < array.length) {
result.push(
callback.call(context, array.slice(i, i + groupSize), i, array)
)
i ++
}
return result
}
map(arr, 2, function (e) {
return e.join("")
})
================================================
ok, one more quick edit: I tweaked slightly further, to eliminate the callback:
function map(array, groupSize) {
var i = 0;
var result = [];
while (i < array.length) {
result.push(array.slice(i, i + groupSize).join(""))
i ++
}
return result
}
map(array, n);
Edit: #torazaburo's idea is actually a nicer separation of concerns than the function I had originally. I didn't realize that there was a name for that process of splitting up an array into fixed-length groups. However, here is my alternate implementation of a partition function because I think it could be a little cleaner, and include an optional offset parameter to allow skipping over the first few elements:
function partition (array, size, offset) {
offset |= 0
var result = []
while (offset < array.length) {
result.push(array.slice(offset, offset += size))
}
return result
}
var arr = ["first", "second", "third", "fourth", "fifth", "sixth" ],
example
// Groups of three, joined by spaces
example = partition(arr, 3).map(function (e) {
return e.join(' ')
})
console.log(example) //=> ["first second third", "fourth fifth sixth" ]
// A list of pairs
example = partition(arr, 2)
console.log(example) //=> [ ["first", "second"], ["third", "fourth"], ["fifth", "sixth"] ]
// A list of one-element arrays, skipping the first element
example = partition(arr, 1, 1)
console.log(example) //=> [ ["second"], ["third"], ["fourth"], ["fifth"], ["sixth"] ]
Original: Alright, it seems that I may have misunderstood your question the first time around. It looks like your goal is to map over groups of array elements; say, pairs instead of one at a time.
Below is a function map, which takes similar arguments to the native Array#map. Don't let the function signature intimidate you too much; it's pretty easy to use and you will rarely need to pass more than three parameters.
function map(array, groupSize, callback, offset, context) {
Parameters:
array — The array that you want to map over.
groupSize — The number of elements that you want to see at a time.
callback — The mapping function that you pass, which receives 1) a group of elements, 2) the index of the first element in the current group, and 3) the original array.
offset — The index at which the first group should begin; allows skipping of elements.
context — Determines what this is bound to in your callback.
Returns:
An array containing the return values, in order, of the calls made to callback for each group of elements.
Demo:
var arr = ["first", "second", "third", "fourth", "fifth", "sixth" ],
example
// Groups of three, joined by spaces
example = map(arr, 3, function (e) {
return e.join(' ')
})
console.log(example) //=> ["first second third", "fourth fifth sixth" ]
// A list of pairs
example = map(arr, 2, function (e) {
return e
})
console.log(example) //=> [ ["first", "second"], ["third", "fourth"], ["fifth", "sixth"] ]
function map(array, groupSize, callback, offset, context) {
var i = offset | 0,
result = []
while (i < array.length) {
result.push(
callback.call(context, array.slice(i, i + groupSize), i, array)
)
i += groupSize
}
return result
}
I think what you are looking for in the notion of "chunking" or "partitioning". This refers to splitting an array into sub-arrays according to some criteria, often length. There are many partitioning solutions out there; here we use a real simple one. However, note that this will destroy the original array.
Once you have partitioned your input, in your case you want to concatenate the elements of each subarray, so
function partition(array, n) {
return array.length ? [array.splice(0, n)].concat(partition(array, n)) : [];
}
var arr = ["first", "second", "third", "fourth", "fifth", "sixth" ];
var int = 3;
const result = partition(arr, int).map(subarray => subarray.join(''))
console.log(result);
Here is a more straight-forward partition implementation:
function partition(array, n) {
let result = [], cnt = 0, sub;
for (let i = 0; i < array.length; i++) {
if (!cnt--) cnt = n, result.push(sub = []);
sub.push(array[i]);
}
return result;
}
array.slice() if you want to leave the original array as it is
or
array.splice() if you want to remove the items from original array
for both functions you pass in the starting index and number of elements from that starting index on to "select/cut" from the original array

Convert set of object's into array item

I have several objects like this:
{'id[0]': 2}
{'url[0]': 11}
{'id[1]': 3}
{'url[1]': 14}
And I want to get something like this:
[{id:2, url:11}, {id:3, url:14}]
Also I have lodash in my project. Maybe lodash have some method for this?
You could use a regular expression for the keys and create a new object if necessary. Then assign the value to the key.
var data = [{ 'id[0]': 2 }, { 'url[0]': 11 }, { 'id[1]': 3 }, { 'url[1]': 14 }],
result = [];
data.forEach(function (a) {
Object.keys(a).forEach(function (k) {
var keys = k.match(/^([^\[]+)\[(\d+)\]$/);
if (keys.length === 3) {
result[keys[2]] = result[keys[2]] || {};
result[keys[2]][keys[1]] = a[k];
}
});
});
console.log(result);
This is an ES6 solution based on #NinaScholz solution.
I assume that the objects have only one property each, like the ones presented in the question.
Combine the array of objects to one large object using Object#assign, and convert to entries with Object.entries.
Iterate the array using Array#reduce.
Extract the original key an value from each entry using array
destructuring.
Extract the wanted key and index using a regex and array
destructuring.
Then create/update the new object at the index using object spread.
const data = [{ 'id[0]': 2 }, { 'url[0]': 11 }, { 'id[1]': 3 }, { 'url[1]': 14 }];
// combine to one object, and convert to entries
const result = Object.entries(Object.assign({}, ...data))
// extract the original key and value
.reduce((r, [k, value]) => {
// extract the key and index while ignoring the full match
const [, key, index] = k.match(/^([^\[]+)\[(\d+)\]$/);
// create/update the object at the index
r[index] = {...(r[index] || {}), [key]: value };
return r;
}, []);
console.log(result);
var arr = [{'id[0]': 2},
{'url[0]': 11},
{'id[1]': 3},
{'url[1]': 14}];
var result = [];
arr.forEach(function(e, i, a){
var index = +Object.keys(e)[0].split('[')[1].split(']')[0];//get the number inside []
result[index] = result[index] || {}; //if item is undefined make it empty object
result[index][Object.keys(e)[0].split('[')[0]] = e[Object.keys(e)[0]];//add item to object
})
console.log(result);
You can use for loop, .filter(), RegExp constructor with parameter "\["+i+"\]" where i is current index, Object.keys(), .reduce(), .replace() with RegExp /\[\d+\]/
var obj = [{
"id[0]": 2
}, {
"url[0]": 11
}, {
"id[1]": 3
}, {
"url[1]": 14
}];
var res = [];
for (var i = 0; i < obj.length / 2; i++) {
res[i] = obj.filter(function(o) {
return new RegExp("\[" + i + "\]").test(Object.keys(o))
})
.reduce(function(obj, o) {
var key = Object.keys(o).pop();
obj[key.replace(/\[\d+\]/, "")] = o[key];
return obj
}, {})
}
console.log(res);

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;
}

Order of the associative array in JavaScript by key and access by index

I have an associative array like:
var arr = {};
arr['alz'] = '15a';
arr['aly'] = '16b';
arr['alx'] = '17a';
arr['alw'] = '09c';
I need to find the previous and next key of any selected element. Say, for key 'aly' it will be 'alz' and 'alx'. If possible, I want to access the array by index rather than the key.
Currently, I am doing this using a separate array containing keys, e.g.
var arrkeys = ['alz','aly','alx','alw'];
Ordering of the object's properties is undefined. You can use this structure...
[{ key: 'alz', value: '15a'},
{ key: 'aly', value: '16b'},
{ key: 'alx', value: '17a'}]
... though searching for the element with the given key (like 'give me the element which key is 'alz') is not as straight-forward as with simple object. That's why using it like you did - providing a separate array for ordering of the indexes - is another common approach. You can attach this array to that object, btw:
var arr={};
arr['alz']='15a';
arr['aly']='16b';
arr['alx']='17a';
arr['alw']='09c';
arr._keysOrder = ['alz', 'aly', 'alx', 'alw'];
This is an object, not an array, and it sounds like you don't really want those strings to be keys.
How about a nice array?
var ar = [
{ key: 'alz', value: '15a' },
{ key: 'aly', value: '16b' },
{ key: 'alx', value: '17a' },
{ key: 'alw', value: '09c' }
];
How about adding some syntactic sugar in the form of an OrderedObject object? Then you could do something like this:
myObj = new OrderedObject();
myObj.add('alz', '15a');
myObj.add('aly', '16b');
myObj.add('alx', '17a');
myObj.add('alw', '09c');
console.log(myObj.keyAt(2)); // 'alx'
console.log(myObj.valueAt(3)); // '09c'
console.log(myObj.indexOf('aly')); // 1
console.log(myObj.length()) // 4
console.log(myObj.nextKey('aly')); // 'alx'
The following code makes this work. See it in action in a jsFiddle.
function OrderedObject() {
var index = [];
this.add = function(key, value) {
if (!this.hasOwnProperty(key)) {
index.push(key);
}
this[key] = value;
};
this.remove = function(key) {
if (!this.hasOwnProperty(key)) { return; }
index.splice(index.indexOf(key), 1);
delete this[key];
}
this.indexOf = function(key) {
return index.indexOf(key);
}
this.keyAt = function(i) {
return index[i];
};
this.length = function() {
return index.length;
}
this.valueAt = function(i) {
return this[this.keyAt(i)];
}
this.previousKey = function(key) {
return this.keyAt(this.indexOf(key) - 1);
}
this.nextKey = function(key) {
return this.keyAt(this.indexOf(key) + 1);
}
}
I made some decisions that may not work for you. For example, I chose to use an Object as the prototype rather than an Array, so that you could preserve enumerating your object with for (key in myObj). But it didn't have to be that way. It could have been an Array, letting you use the property .length instead of the function .length() and then offering an each function that enumerates the keys, or perhaps an .object() function to return the inner object.
This could be a little awkward as you'd have to remember not to add items to the object yourself. That is, if you do myObj[key] = 'value'; then the index will not be updated. I also did not provide any methods for rearranging the order of things or inserting them at a particular position, or deleting by position. If you find my object idea useful, though, I'm sure you can figure out how to add such things.
With the newer versions of EcmaScript you can add true properties and make them non-enumerable. This would allow the new object to more seamlessly and smoothly act like the ideal OrderedObject I am imagining.
If you have to know the order of everything, and still use the keys and values, try this:
var arr = [
{ key: 'alz', value: '15a' },
{ key: 'aly', value: '16b' },
{ key: 'alx', value: '17a' },
{ key: 'alw', value: '09c' }
];
You can then access them sequentially as follows: arr[0].key and arr[0].value. Similarly, you can find siblings inside of the loop with the following:
for(var i = 0; i < arr.length; i++)
{
var previous_key = (i > 0) ? arr[(i - 1)].key : false;
var next_key = (i < (arr.length - 1)) ? arr[(i + 1)].key : false;
}
You may try this
function sortObject(obj, order)
{
var list=[], mapArr = [], sortedObj={};
for(var x in obj) if(obj.hasOwnProperty(x)) list.push(x);
for (var i=0, length = list.length; i < length; i++) {
mapArr.push({ index: i, value: list[i].toLowerCase() });
}
mapArr.sort(function(a, b) {
if(order && order.toLowerCase()==='desc')
return a.value < b.value ? 1 : -1;
else return a.value > b.value ? 1 : -1;
});
for(var i=0; i<mapArr.length;i++)
sortedObj[mapArr[i].value]=obj[mapArr[i].value];
return sortedObj;
}
// Call the function to sort the arr object
var sortedArr = sortObject(arr); // Ascending order A-Z
var sortedArr = sortObject(arr, 'desc'); // Descending order Z-A
DEMO.
Remember, this will return a new object and original object will remain unchanged.

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