Related
I have the below array of objects and I want to check if two different users are present in this array .if present i have to run some logic
let result = [{"name": "ABC"},{"name": "CDE"},{"name": "FGH"},{"name": "XYZ"}];
var newArr = [];
var hasMatch = result.filter(function(val) {
if (val.name == "FGH"){
newArr.push(val)
} else if (val.name == "ABC") {
newArr.push(val)
}
});
console.log(newArr)
if (newArr.length == 2) {
//do logic
}
It's working as expected but I'm looking for a different approach for this. could someone advise?
Not optimized for speed, but does the job
let arr = [
{
"name": "ABC"
},
{
"name": "CDE"
},
{
"name": "FGH"
},
{
"name": "XYZ"
}
];
let users = ["ABC", "XYZ"]
let hasAllUsers = users.every(user => arr.some(item => item.name == user))
console.log(hasAllUsers)
// if(hasAllUser) {...}
It's a pretty roundabout way to zero in on the logic you're trying to express. Note how the result in hasMatch is never even used. That's really all you're looking for, does the array "have the values".
There's no need to push values to another array and check if that array has values. Just check of the original array has them.
Which could be as simple as:
let result = [{"name": "ABC"},{"name": "CDE"},{"name": "FGH"},{"name": "XYZ"}];
if (result.filter(r => r.name === "FGH" || r.name === "ABC").length === 2) {
// do logic
}
Or if you want to refactor the condition into a variable:
let result = [{"name": "ABC"},{"name": "CDE"},{"name": "FGH"},{"name": "XYZ"}];
let hasMatch = result.filter(r => r.name === "FGH" || r.name === "ABC").length === 2;
if (hasMatch) {
// do logic
}
Or a bit more verbose for clarity:
let result = [{"name": "ABC"},{"name": "CDE"},{"name": "FGH"},{"name": "XYZ"}];
let filteredResult = result.filter(r => r.name === "FGH" || r.name === "ABC");
let hasMatch = filteredResult.length === 2;
if (hasMatch) {
// do logic
}
You can simply create another array with the valid users and filter your array to match each items that are this array.
This can be done using the Array#includes method
const users = [{"name": "ABC"},{"name": "CDE"},{"name": "FGH"},{"name": "XYZ"}];
const validUsers = ["ABC", "FGH", "AnotherUser"];
const matchUsers = users.filter(user => validUsers.includes(user.name))
console.log(matchUsers)
You could count the wanted names.
const
data = [{ name: "ABC" }, { name: "CDE" }, { name: "FGH" }, { name: "XYZ" }],
names = ['ABC', 'FGH'],
result = data.reduce((t, { name }) => t + names.includes(name), 0);
console.log(result);
Try using a named function and pass in the array, key, and one or more values with the rest operator ...values. Use .flatMap() to filter with
[...values].includes(obj[key])
// ["ABC", "XYZ"].includes(obj.name)
and any non-match returns an empty array []. The final return is an array with a sub-array and the length of said sub-array.
const result = [["ABC", "XYZ"], 2]
// result[0][0] = "ABC"
// result[0][1] = "XYZ"
// result[1] = 2
const arr = [{"name": "ABC"},{"name": "CDE"},{"name": "FGH"},{"name": "XYZ"}];
function hasMatch(array, key, ...values) {
const result = array.flatMap((obj, idx) =>
[...values].includes(obj[key]) ? obj : []);
return [result, result.length];
}
console.log(hasMatch(arr, "name", "ABC", "XYZ"));
console.log(hasMatch(arr, "name", "FGH", "IJK", "LMN", "ABC", "XYZ"));
["10","13"] is the array, need to find the values between them and flatten the array with the values -> ["10","11","12","13"].
The first array above (["10", "13"]) is in a list of arrays.
const OriginalData = {
Red:{
Name:"L",
List:[
["1", "5"],
["2", "5"],
["7", "9" ],
]
},
Blue:{
Name:"BL",
List:[
["1", "5"],
["7", "9" ],
["10", "13" ],
["15", "20"]
]
},
Black:{
List:[
["Random"],
"Random2"
]
}
}
Then finally Object must look like,
{
Level:{
Name:"L",
List:[
1, 2, 3, 4, 5, 7, 8, 9
]
},
Basement:{
Name:"BL",
List:[
1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20
]
},
Custom:{
List:[
"Random",
"Random2"
]
}
}
What It should do:
Take the first object, inside List there are set of ranges, the values between those ranges should be found a flatten without duplicates.
Finding the values between is only for "Red", and "Blue", In "Black" key only flatten is needed.
I tried,
Code:
const submitData = () => {
let obj = originalData;
let flattenedArray = [].concat.apply([], originalData.Red.List);
let uniqueArray = flattenedArray.filter(
(v, i, a) => a.indexOf(v) === i
);
obj = {
...originalData,
Red: {
...originalData.Red,
List: uniqueArray,
},
};
console.log(obj);
};
The above code flattens the array but will not find between the numbers and it only worked for key "Red"
A simple example to create a range:
let example = ["10","13"];
let min = Math.min(...example);
let max = Math.max(...example);
let result = [];
for (i = min; i <= max; i++) {
result.push(i);
}
console.log(min, max, result)
You can easily achieve it with a simple logic and will work for random numbers as well.
Try this (Descriptive comments of implementation has been added in the below code snippet) :
const OriginalData = {
Red:{
Name:"L",
List:[
["1", "5"],
["2", "5"],
["7", "9" ],
]
},
Blue:{
Name:"BL",
List:[
["1", "5"],
["7", "9" ],
["10", "13" ],
["15", "20"]
]
}
};
Object.keys(OriginalData).forEach(key => {
// Flatten the original array list.
OriginalData[key].List = OriginalData[key].List.flat()
// Find min and max numbers from the array.
const min = Math.min(...OriginalData[key].List);
const max = Math.max(...OriginalData[key].List);
// empty existing list array.
OriginalData[key].List = [];
// Now using for loop assign the values to the list array based on min and max value.
for (let i = min; i <= max; i++) {
OriginalData[key].List.push(i);
}
});
// Result
console.log(OriginalData);
To create an array of all the numbers in a given range, you can create a new array with the required size and then map each of it's entries to the entry's index plus the given lower bound.
function fillRange(r) {
let b = +r[1]
let a = +r[0]
if (a > b) {
let tmp = a
a = b
b = tmp
}
return Array(b - a + 1).fill(0).map((e, i) => a + i)
}
This function flattens an array and removes all duplicate entries.
function union(arrays) {
let flattened = [].concat.apply([], arrays)
return flattened.reduce(
(total, e) => {
let i = total.indexOf(e)
if (i === -1) {
total.push(e)
}
return total
}, [])
}
Then this code produces the desired result from a list of ranges:
function unionRanges(ranges) {
let expanded = ranges.map((e) => fillRange(e))
return union(expanded).sort((a,b) => (a-b))
}
The final object can be created like this:
function processData(data) {
let res = {}
res.Level = {}
res.Basement = {}
res.Custom = {}
res.Level.Name = data.Red.Name;
res.Level.List = unionRanges(data.Red.List)
res.Basement.Name = data.Blue.Name
res.Basement.List = unionRanges(data.Blue.List)
res.Custom.List = union(data.Black.List)
return res
}
You can flat the array, get the min and max and finally with a loop create the desired array.
const array = [["1","5"],["7","9"],["10","13"],["15","20"]];
const flatted = array.flat();
const min = Math.min(...flatted);
const max = Math.max(...flatted);
const result = Array.from({length: max + 1 - min}).map(function(_, i) {
return i + min;
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Hope the below codes help you.
const OriginalData = {
Red: {
Name: "L",
List: [
["1", "5"],
["2", "5"],
["7", "9"],
]
},
Blue: {
Name: "BL",
List: [
["1", "5"],
["7", "9"],
["10", "13"],
["15", "20"]
]
},
Black: {
List: [
["Random"],
"Random2"
]
}
};
//Iterating over the object OriginalData
Object.keys(OriginalData).forEach(key => {
// Flatten the array "List" of each element
OriginalData[key].List = OriginalData[key].List.flat();
// Checking if the flatten array contains integers
if (!isNaN(parseInt(OriginalData[key].List[0]))) {
// Calculating the min and max of the "List" array
const min = Math.min(...OriginalData[key].List);
const max = Math.max(...OriginalData[key].List);
let tmpArr = [];
// Generating the array with numbers from min to max
for (let i = min; i <= max; i++) {
tmpArr.push(i);
}
// Updating the original "List" (containing integers) of each element
OriginalData[key].List = tmpArr;
}
});
console.log(OriginalData);
I would like to push key values to objects in array1 from other objects of array2
To do so it needs to search a corresponding values in both arrays, then push the right key.
let array1 = [
{
"Ref": "28189-060-B",
"Otherkey": "Whatever"
},
{
"Ref": "18182-250-B",
"Otherkey": "Whatever2"
},
{
"Ref": "55187-753-B",
"Otherkey": "Whatever3"
}
]
let array2 = [
{
"Ref": "28189-060-ABCD",
"Style": "Red"
},
{
"Ref": "18182-250-ABCD",
"Style": "Blue"
},
{
"Ref": "55187-753-ABCD",
"Style": "Yellow"
}
]
The function need to loop through all objects in array1, look at the first 9 characters of Ref values, find a match in array2 Ref (only first 9 characters are identical). When there is a match push the "Style" from array2 into the corresponding object in array1
I tried with Object.key.foreach(), map(), with substr to get only 9 characters, with find()... all of this has been a big mess and not working...
Expected result :
let array1 = [
{
"Ref": "18182-250-B",
"Otherkey": "Whatever2",
"Style": "Blue"
},
{
"Ref": "28189-060-B",
"Otherkey": "Whatever",
"Style": "Red"
},
{
"Ref": "55187-753-B",
"Otherkey": "Whatever3",
"Style": "Yellow"
}
]
Assuming those properties are all meant to be Ref (some are Global_Style), you can use forEach and find:
let array1 = [{"Ref":"28189-060-B","Otherkey":"Whatever"},{"Ref":"18182-250-B","Otherkey":"Whatever2"},{"Ref":"55187-753-B","Otherkey":"Whatever3"}];
let array2 = [{"Ref":"28189-060-ABCD","Style":"Red"},{"Ref":"18182-250-ABCD","Style":"Blue"},{"Ref":"55187-753-ABCD","Style":"Yellow"}];
const shorterRef = (ref) => ref.substr(0, 9);
array1.forEach(obj => {
const a1Ref = shorterRef(obj.Ref);
const arr2Obj = array2.find(tmp => shorterRef(tmp.Ref) === a1Ref);
if (arr2Obj) obj.Style = arr2Obj.Style;
});
console.log(array1);
If you didn't want to mutate the array go with map:
let array1 = [{"Ref":"28189-060-B","Otherkey":"Whatever"},{"Ref":"18182-250-B","Otherkey":"Whatever2"},{"Ref":"55187-753-B","Otherkey":"Whatever3"}];
let array2 = [{"Ref":"28189-060-ABCD","Style":"Red"},{"Ref":"18182-250-ABCD","Style":"Blue"},{"Ref":"55187-753-ABCD","Style":"Yellow"}];
const shorterRef = (ref) => ref.substr(0, 9);
const out = array1.map(obj => {
const a1Ref = shorterRef(obj.Ref);
const arr2Obj = array2.find(tmp => shorterRef(tmp.Ref) === a1Ref);
if (arr2Obj) return { ...obj, Style: arr2Obj.Style };
});
console.log(out);
var arrMap = {};
array1.forEach(function(x){
if(!arrMap[x.Ref.substring(0,9)]){
arrMap[x.Ref.substring(0,9)] = x;
}
});
array2.forEach(function(x){
if(Object.keys(arrMap).includes(x.Ref.substring(0,9))){
arrMap[x.Ref.substring(0,9)] = Object.assign(arrMap[x.Ref.substring(0,9)], {"Style": x.Style});
}
});
console.log(Object.values(arrMap));
Something like this may be what you want:
array1.forEach(function (element1) {
array2.forEach(function (element2){
addStyle(element1, element2);
});
});
function addStyle(obj1, obj2){
if (obj1.Ref && obj2.Ref){
let Ref1 = obj1.Ref.substr(0,8);
let Ref2 = obj2.Ref.substr(0, 8);
if (Ref1 === Ref2){
obj1.Style = obj2.Style;
};
}
}
So we loop through the fist array and for each item we loop through the second array.
Then we check if the expected fields are present and if so we compare them. If they match we add the "Style" field and move to the next object
The Below code will work although we might be able to optimize it further.
var newArr = []
for(let k in array1){
for(let i in array2){
console.log(array2[i]['Ref'].substr(0,9))
if(array1[k]['Ref'].substr(0,9) == array2[i]['Ref'].substr(0,9)){
let temp = array1[k]
temp['Style'] = array2[i]['Style']
newArr.push(temp)
}
}
}
The first solution is a bit complex.
You probable have a typo in array1 as your first key is not consistent. instead of Global_Stylecode you probably meant Ref, Anyway most likely it should have the same key. If we assume that the key is Ref, then
array1.forEach( ({Ref: Ref1, Otherkey}, index) => {
const Ref1Sub = Ref1.substring(0, 9);
array2.forEach(({Ref: Ref2, Style}) => {
if (Ref2.includes(Ref1Sub)) {
array1[index].Style = Style;
}
})
});
Also there is no need to define arrays as let. const will be fine.
I know the title might sounds confusing, but i'm stuck for an hour using $.each. Basically I have 2 arrays
[{"section_name":"abc","id":1},{"section_name":"xyz","id":2}];
and [{"toy":"car","section_id":1},{"tool":"knife","section_id":1},{"weapons":"cutter","section_id":2}];
How do I put one into another as a new property key like
[{
"section_name": "abc",
"id": 1,
"new_property_name": [{
"toy": "car"
}, {
"tool": "knife"
}]
}, {
"section_name": "xyz",
"id": 2,
"new_property_name": [{
"weapon": "cutter"
}]
}]
ES6 Solution :
const arr = [{"section_name":"abc","id":1},{"section_name":"xyz","id":2}];
const arr2 = [{"toy":"car","id":1},{"tool":"knife","id":1},{"weapons":"cutter","id":2}];
const res = arr.map((section,index) => {
section.new_property_name = arr2.filter(item => item.id === section.id);
return section;
});
EDIT : Like georg mentionned in the comments, the solution above is actually mutating arr, it modifies the original arr (if you log the arr after mapping it, you will see it has changed, mutated the arr and have the new_property_name). It makes the .map() useless, a simple forEach() is indeed more appropriate and save one line.
arr.forEach(section => {
section.new_property_name = arr2.filter(item => item.id === section.id));
});
try this
var data1 = [{"section_name":"abc","id":1},{"section_name":"xyz","id":2}];
var data2 = [{"toy":"car","id":1},{"tool":"knife","id":1},{"weapons":"cutter","id":2}];
var map = {};
//first iterate data1 the create a map of all the objects by its ids
data1.forEach( function( obj ){ map[ obj.id ] = obj });
//Iterate data2 and populate the new_property_name of all the ids
data2.forEach( function(obj){
var id = obj.id;
map[ id ].new_property_name = map[ id ].new_property_name || [];
delete obj.id;
map[ id ].new_property_name.push( obj );
});
//just get only the values from the map
var output = Object.keys(map).map(function(key){ return map[ key ] });
console.log(output);
You could use ah hash table for look up and build a new object for inserting into the new_property_name array.
var array1 = [{ "section_name": "abc", "id": 1 }, { "section_name": "xyz", "id": 2 }],
array2 = [{ "toy": "car", "section_id": 1 }, { "tool": "knife", "section_id": 1 }, { "weapons": "cutter", "section_id": 2 }],
hash = Object.create(null);
array1.forEach(function (a) {
a.new_property_name = [];
hash[a.id] = a;
});
array2.forEach(function (a) {
hash[a.section_id].new_property_name.push(Object.keys(a).reduce(function (r, k) {
if (k !== 'section_id') {
r[k] = a[k];
}
return r;
}, {}));
});
console.log(array1);
Seems like by using Jquery $.merge() Function you can achieve what you need. Then we have concat function too which can be used to merge one array with another.
Use Object.assign()
In your case you can do it like Object.assign(array1[0], array2[0]).
It's very good for combining objects, so in your case you just need to combine your objects within the array.
Example of code:
var objA = [{"section_name":"abc","id":1},{"section_name":"xyz","id":2}];
var objB = [{"toy":"car","section_id":1},{"tool":"knife","section_id":1},{"weapons":"cutter","section_id":2}];
var objC = Object.assign({},objA[0],objB[0]);
console.log(JSON.stringify(objC));// {"section_name":"abc","id":1,"toy":"car","section_id":1}
For more info, you can refer here: Object.assign()
var firstArray = [{"section_name":"abc","id":1},{"section_name":"xyz","id":2}],
secondArray = [{"toy":"car","section_id":1},{"tool":"knife","section_id":1},{"weapons":"cutter","section_id":2}];
var hash = Object.create(null);
firstArray.forEach(s => {
hash[s.id] = s;
s['new_property_name'] = [];
});
secondArray.forEach(i => hash[i['section_id']]['new_property_name'].push(i));
console.log(firstArray);
I have an object in this format:
var request = {
"student": [
[
"name",
"age"
],
[
"Tom",
12
],
[
"Jack",
13
]
]
};
I want to transform it into this:
var request = {
"student": [
{
"name": "Tom",
"age": 12
},
{
"name": "Jack",
"age": 13
}
]
}
I tried doing it this way:
var response = [];
var keysCount = req.result[0].length;
var responseCount = req.result.length - 1;
var i = 0,
j = 0,
key;
for (j = 0; j < responseCount; j++) {
for (i = 0; i < keysCount; i++) {
key = req.result[0][i];
response[j][key] = req.result[j + 1][i];
}
}
return response;
But, it is not working as expected.
It's a matter of looping through the first array and creating an array of objects for all the remaining arrays, using values at matching indexes to create properties on object:
var request = {
"student": [
[
"name",
"age"
],
[
"Tom",
12
],
[
"Jack",
13
]
]
};
// Get the header array
var headers = request.student[0];
// Create the new array but mapping the other entries...
var newArray = request.student.slice(1).map(function(entry) {
// Create an object
var newEntry = {};
// Fill it in with the values at matching indexes
headers.forEach(function(name, index) {
newEntry[name] = entry[index];
});
// Return the new object
return newEntry;
});
console.log(newArray);
I would make a small function tabularize that takes an array of data where the first element is an array of headers, and the remaining elements are the rows
Code that follows uses ES6. If you need ES5 support, you can safely transpile this code using a tool like babel.
// your original data
var request = {
"student": [
[
"name",
"age"
],
[
"Tom",
12
],
[
"Jack",
13
]
]
};
// tabularize function
var tabularize = ([headers, ...rows])=>
rows.map(row=>
headers.reduce((acc,h,i)=>
Object.assign(acc, {[h]: row[i]}), {}));
// your transformed object
var request2 = {student: tabularize(request.student)};
// log the output
console.log(request2);
//=> {"student":[{"name":"Tom","age":12},{"name":"Jack","age":13}]}
Or you can create the request object with the intended shape by passing the tabular data directly into the tabularize function at the time of object creation
// tabularize function
var tabularize = ([headers, ...rows])=>
rows.map(row=>
headers.reduce((acc,h,i)=>
Object.assign(acc, {[h]: row[i]}), {}));
// your request object
var request = {
student: tabularize([
[
"name",
"age"
],
[
"Tom",
12
],
[
"Jack",
13
]
])
};
// log the output
console.log(request);
//=> {"student":[{"name":"Tom","age":12},{"name":"Jack","age":13}]}
Let's start off by writing a little function just to create an object from two arrays, one of keys and one of their values:
function makeObjectFromPairs(keys, values) {
var object = {};
for (var i = 0; i < keys.length; i++) {
object[keys[i]] = values[i];
}
return object;
}
// makeObjectFromPairs(['a', 'b'], [1, 2]) === {a: 1, b: 2}
Now we can use the first element of the students array as the keys, and each of the remaining elements as the values.
var keys = students[0];
var result = [];
for (var i = 1; i < students.length; i++) {
result.push(makeObjectFromPairs(keys, students[i]);
}
You could use Array#map etc. as an alternative for the loops, but perhaps this basic approach is more accessible.
Fixing your original code
Since you made a valiant effort to solve this yourself, let's review your code and see where you went wrong. The key point is that you are not initializing each element in your output to an empty object before starting to add key/value pairs to it.
for (j = 0; j < responseCount; j++) {
// Here, you need to initialize the response element to an empty object.
response[j] = {};
Another solution :
var request = {
"student": [
[
"name",
"age"
],
[
"Tom",
12
],
[
"Jack",
13
]
]
};
var response = {};
var students = [];
var responseCount = request.student.length - 1;
var j = 0,
key;
for (j = 0; j < responseCount; j++) {
var student = {};
request.student[0].forEach(function(name, index) {
student[name] = request.student[1 + j][index];
});
students.push(student)
}
response["students"] = students;
console.log(response); // {"students":[{"name":"Tom","age":12},{"name":"Jack","age":13}]}
Lodash solution
var keys = _.head(request.student);
var valueGroups = _.flatten(_.zip(_.tail(request.student)));
var studentObjects = valueGroups.map(function(values){
return values.reduce(function(obj, value, index){
obj[keys[index]] = value;
return obj;
}, {});
});
console.log(studentObjects);
https://jsfiddle.net/mjL9c7wt/
Simple Javascript solution :
var request = {
"student": [
[
"name",
"age"
],
[
"Tom",
12
],
[
"Jack",
13
]
]
};
var students = [];
for(var x = 1; x<request.student.length;x++)
{
var temp = { 'name' : request.student[x][0],
'age' : request.student[x][1]
}
students.push(temp);
}
request = { 'students' : students}
console.log(request);