var list = [
{name :a,id:1,index:1},
{name :a,id:1,index:2},
{name :b,id:2,index:3},
{name :c,id:3,index:4},
{name :b,id:2,index:5},
];
i want to avoid the above situation , here object having name = a
coming twice consecutively. But whereas object having name = b
is acceptable
i expect some buil it funtion which will find these type of objects. just like isNaN
tried with plain javascript but need function in underscore.
Downvoters pls comment before down voting :)
You coud use Array#every for the check. It stops the iteration if a result is false.
var list = [{ name: 'a', id: 1, index: 1 }, { name: 'a', id: 1, index: 2 }, { name: 'b', id: 2, index: 3 }, { name: 'c', id: 3, index: 4 }, { name: 'b', id: 2, index: 5 }],
notConsecutive = list.every(function (a, i, aa) {
return !i || aa[i - 1].name !== a.name;
});
console.log(notConsecutive);
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 months ago.
Improve this question
I want all the name1 and name2 to be unique in every sub-array
[
{ id: 1, name1: a, name2: b },
{ id: 2, name1: c, name2: d },
{ id: 3, name1: e, name2: a }
],
[
{ id: 4, name1: t, name2: k },
{ id: 5, name1: j, name2: h },
{ id: 6, name1: z, name2: x },
],
]
In this example id-1 name1 and id-3 name2 have the value 'a', so I pushed id-3 to the next sub-array where there are no name1 and name2 matching id-3s name1 and name2.
[
{ id: 1, name1: a, name2: b },
{ id: 2, name1: c, name2: d },
],
[
{ id: 4, name1: t, name2: k },
{ id: 5, name1: j, name2: h },
{ id: 6, name1: z, name2: x },
{ id: 3, name1: e, name2: a },
],
]
If there's no such sub-array where id-3 name1 and name2 will be unique I want to create a new sub array and push id-3 into that.
You can build functions which determine whether a particular object is a "duplicate", then iterate your array, filtering out the duplicates and pushing them to the next entry in the array. If they are also a dupe in that entry, they will be pushed to the next entry, and so on...
const data = [
[
{ id: 1, name1: 'a', name2: 'b' },
{ id: 2, name1: 'c', name2: 'd' },
{ id: 3, name1: 'e', name2: 'a' }
],
[
{ id: 4, name1: 't', name2: 'k' },
{ id: 5, name1: 'j', name2: 'h' },
{ id: 6, name1: 'z', name2: 'x' },
],
]
// function to determine if an object's name1 or name2
// property exists in an other object with a lower index
const isdupe = (obj, idx, arr) =>
arr.findIndex(({ name1, name2 }, i) => [name1, name2].includes(obj.name1) || [name1, name2].includes(obj.name2)) != idx
const isnotdupe = (obj, idx, arr) => !isdupe(obj, idx, arr)
// iterate over the entries in the data array
for (let i = 0; i < data.length; i++) {
// find the duplicates in this array
let dupes = data[i].filter(isdupe)
// if there are any, add (concat) them to the next array
// (data[i+1] || []) will create a new entry if one doesn't exist
if (dupes.length) data[i+1] = (data[i+1] || []).concat(dupes)
// filter this array to only be non-duplicates
data[i] = data[i].filter(isnotdupe)
}
console.log(data)
I'm not quite sure what your asking for here, as you seem to grasp the concept, but i'm going to try and answer it, so appologies if its not a 100% fitting answer.
Every time that an item is added to the array, you could create a for statement that goes through every item on the array and checks if(item == new item) then it pushes it to array two, and repeats the checking process.
If you are asking for the specific commands related to it, a great resorce I use is https://www.w3schools.com
More specificaly for this question, https://www.w3schools.com/jsref/jsref_includes_array.asp
I have an array of object - like this -
test: [
{
id:'1',
name:'A'
},
{
id:'2',
name:'B'
},
]
Suppose I have a value 2 that exists in object Test as id. I want to get whole object from array if id value exists in whole array
input - 2,
expected output - {id:'2' , name:'B'}
How Can we get it ? is it any possible solution ?
Simply use find-
const val = [
{
id: '1',
name: 'A',
},
{
id: '2',
name: 'B',
},
];
const res = val.find(obj => obj.id === '2');
console.log(res);
There can be multiple ways to do this. Here is how I did it.
let test = [
{
id: '1',
name: 'A'
},
{
id: '2',
name: 'B'
}
];
let result = (param) => test.filter(el => {
return el.id == param
});
console.log(result(2))
i have a 2 object which i wan't to make filtering with es6
first is my data object and second selected some data.
I wan't to get all items in data object which have second object values
let data = [
{
id: 1,
name: 'A',
status: 1
},
{
id: 2,
name: 'B',
status: 1
},
{
id: 3,
name: 'C',
status: 3
},
{
id: 4,
name: 'D',
status: 2
}
]
and second object is :
let selectedStatus = [
{
id: 1,
status: 1
},
{
status: 3
}
]
in this case i want't to get data object items which contains same statuses in second object so in this case i need to get this result:
data = [
{
id: 1,
name: 'A',
status: 1
},
{
id: 2,
name: 'B',
status: 1
},
{
id: 3,
name: 'C',
status: 3
},
]
You can do like this:
data = data.filter(item =>
selectedStatus.map(s => s.status).includes(item.status)
);
Below snippet will give the expected answer:
var result = [];
data.forEach((value) => {
selectedStatus.forEach(val => {
if(value.status == val.status) {
result.push(value)
}
});
});
console.log(result)
Assuming you do not have any browser restrictions, you can make use of followed by using Array.includes() to check statuses on data which are on selectedStatus, followed by Array.filter() to filter out objects which match the required condition.
const data = [
{
id: 1,
name: 'A',
status: 1
},
{
id: 2,
name: 'B',
status: 1
},
{
id: 3,
name: 'C',
status: 3
},
{
id: 4,
name: 'D',
status: 2
}
]
const selectedStatus = [
{
id: 1,
status: 1
},
{
status: 3
}
];
const res = data.filter(obj => selectedStatus.map(s => s.status).includes(obj.status));
console.log(res);
let result = [];
selectedStatus.forEach(selectedStatus => result = result.concat(data.filter(status => status.status === selectedStatus.status)))
If you want to generate a third list, like your expected result, you can generate a white-list to match against.
const whiteList = selectedStatus.map((sel) => sel.status); // which gives you an array of all selected status you want to filter for
const filteredData = data.filter((data) => ~whiteList.indexOf(data.status)); // please consider that filter returns a new array that contain all items where the condition was falsy. That can be confusing.
to understand the ~ operator please check
https://wsvincent.com/javascript-tilde/
you may struggle with the result of the filtered array. Please consider that array.filter returns a new array that contain all items which did NOT met the condition in other words its a negation. That can be confusing.
https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
ES7
const filteredData = data.filter((data) => whiteList.includes(data.status));
This question already has answers here:
How do I sort an array of objects based on the ordering of another array?
(9 answers)
Javascript - sort array based on another array
(26 answers)
Closed 4 years ago.
I have two arrays.
itemsArray =
[
{ id: 8, name: 'o'},
{ id: 7, name: 'g'},
{ id: 6, name: 'a'},
{ id: 5, name: 'k'},
{ id: 4, name: 'c'}
]
sortArray = [4,5]
How can i sort itemsArray by sortArray (lodash or pure), but i want to for this:
newArray =
[
{ id: 4, name: 'c'},
{ id: 5, name: 'k'},
{ id: 8, name: 'o'},
{ id: 7, name: 'g'},
{ id: 6, name: 'a'}
]
In a case like this where you want to sort on multiple levels, you need to sort them in descending order of importance inside your sorting function.
In this case we sort regularly on cases where both elements are either in or not in the sorting array.
var itemsArray = [
{ id: 8, name: 'o' },
{ id: 7, name: 'g' },
{ id: 6, name: 'a' },
{ id: 5, name: 'k' },
{ id: 4, name: 'c' }
];
var sortArray = [4, 5];
var sortedItemsArray = itemsArray.sort(function (a, b) {
if (sortArray.includes(a.id) == sortArray.includes(b.id)) { //both or neither are in sort array
return b.id - a.id;
}
else if (sortArray.includes(a.id)) { //only a in sort array
return -1;
}
else { //only b in sort array
return 1;
}
});
console.log(sortedItemsArray);
The above snippet could be expanded in multiple ways, but a popular approach is to separate it into several sorting steps.
var itemsArray = [
{ id: 8, name: 'o' },
{ id: 7, name: 'g' },
{ id: 6, name: 'a' },
{ id: 5, name: 'k' },
{ id: 4, name: 'c' }
];
var sortArray = [4, 5];
function sortId(a, b) {
return b.id - a.id;
}
function sortIdByList(a, b) {
if (sortArray.includes(a.id)) {
return -1;
}
if (sortArray.includes(b.id)) {
return 1;
}
return 0;
}
//TEST
var sortedItemsArray = itemsArray
.sort(sortId)
.sort(sortIdByList);
console.log(sortedItemsArray);
This pattern can be easier to maintain as each step is clearly labeled and the functions can be reused in other sorting cases.
The only downside to this pattern is that you end up iterating over the list multiple times, thus increasing the time to sort. Usually this is a non-issue but on very large lists this can be significant.
Sort by array index only
As the comments points out i misread the question, so my previous two sorting snippets doesn't necessarily give the desired result.
This version sorts only by id index in the sorting array:
var itemsArray = [
{ id: 8, name: 'o' },
{ id: 7, name: 'g' },
{ id: 6, name: 'a' },
{ id: 5, name: 'k' },
{ id: 4, name: 'c' }
];
var sortArray = [4, 5];
//TEST
var sortedItemsArray = itemsArray
.sort(function (a, b) {
//Calculate index value of a
var A = sortArray.indexOf(a.id);
if (A == -1) {
A = sortArray.length;
}
//Calculate index value of b
var B = sortArray.indexOf(b.id);
if (B == -1) {
B = sortArray.length;
}
//Return comparison
return A - B;
});
console.log(sortedItemsArray);
You could take the indices of the array for keeping the relative position and take the special items with a negative index to top for sorting.
Then sort the array by taking the indices.
var array = [{ id: 8, name: 'o' }, { id: 7, name: 'g' }, { id: 6, name: 'a' }, { id: 5, name: 'k' }, { id: 4, name: 'c' }],
sortArray = [4, 5],
indices = array.reduce((r, { id }, i) => (r[id] = i, r), {});
sortArray.forEach((id, i, { length }) => indices[id] = i - length);
array.sort(({ id: a }, { id: b }) => indices[a] - indices[b]);
console.log(array);
console.log(indices);
.as-console-wrapper { max-height: 100% !important; top: 0; }
How can I compare multiple arrays of objects and add new properties with the number of occurrences an object was found and the array indexes where the object was found?
The object comparison must be made by the name property.
Example:
var arrays = [
[
{
name: 'aa',
value: 1
},
{
name: 'ab',
value: 2
},
{
name: 'ac',
value: 3
},
{
name: 'aa',
value: 1
}
],
[
{
name: 'aa',
value: 1
},
{
name: 'ab',
value: 2
},
],
[
{
name: 'ac',
value: 3
},
{
name: 'aa',
value: 1
}
]
]
After execution the object from the above array should have these properties:
[
[
{
name: 'aa',
value: 1,
occurrences: 3,
where: [0, 1, 2]
},
{
name: 'ab',
value: 2,
occurrences: 2,
where: [0, 1]
},
{
name: 'ac',
value: 3,
occurrences: 2,
where: [0, 2]
},
{
name: 'aa',
value: 1,
occurrences: 3,
where: [0, 1, 2]
}
],
[
{
name: 'aa',
value: 1,
occurrences: 3,
where: [0, 1, 2]
},
{
name: 'ab',
value: 2,
occurrences: 2,
where: [0, 1]
}
],
[
{
name: 'ac',
value: 3,
occurrences: 2,
where: [0, 2]
},
{
name: 'aa',
value: 1,
occurrences: 3,
where: [0, 1, 2]
}
]
]
Basically I want to check if the object with a specific name property exists in the other arrays.
This is the solution that comes in my mind:
1. Loop through the array that has the most objects
2. Loop through each object
3. Loop through the other arrays and apply Array.prototype.find()
But this will take a lot of time since each of my array will have at least 500 objects...
You can use array#reduce to get the number of occurrences and the index of occurrences in an object.
Then, you can modify your object in the arrays by simply using Object.assign() and adding the where and occurrences property.
var arrays = [ [ { name: 'aa', value: 1 }, { name: 'ab', value: 2 }, { name: 'ac', value: 3 }, { name: 'aa', value: 1 } ], [ { name: 'aa', value: 1 }, { name: 'ab', value: 2 }, ], [ { name: 'ac', value: 3 }, { name: 'aa', value: 1 } ] ];
var result = arrays.reduce((res, arr, index) => {
arr.forEach(({name,value}) => {
res[name] = res[name] || {occurrences: 0};
res[name]['where'] = res[name]['where'] || [];
if(!res[name]['where'].includes(index)){
res[name]['where'].push(index);
res[name].occurrences += 1;
}
});
return res;
},{});
arrays.forEach(arr => arr.forEach(obj => Object.assign(obj, result[obj.name])));
console.log(arrays);
This looked like trivial reduce, until i noticed nested arrays ) so it's more like flatten + reduce, with memory.
Code below is doing what you need, just the prop names are short (as i type them on the phone):
let f = (ai, a,v,i,m) => {
if (!a[v.id]) {
a[v.id] = {id: v.id, v: v.name, count: 1, at: [ai]};
} else {
a[v.id].count += 1;
a[v.id].at.push(ai);
}
return a;
};
let r = [[{id: 'aa', value: 42}], [{id: 'ba', value: 11}, {id: 'aa', value: 42}]]
.reduce ((a, v, i) => v.reduce (f.bind (null, i),a), {});
console.log (r);
Code still visits each element in any array only once, so complexity is O(n), and there should not be a problem running it on arrays up to a million of total elements (e.g. 1000 arrays of 1000 elements, or 200 x 5000).