I am trying to add multiple objects- Company Names into listBox Companies. I used $scope.companies.push(newCompany[0].name); to add the company into the list. But only the first object's company gets added because I used newCompany[0].name.
Now, how do I add the second company name into the list without entering newCpmpany[1].name ? Say there are 50 companies, I cannot add all 50 by doing this. Is there a better way to add all the names in one go? like a loop or incrementing the element or something? Looking for some help. Thanks in advance.
var newCompany = [{
name: "Huawei", // -->COMPANY NAME
email: "Drath#yahoo.com",
phone: "123-123-1234",
owner: "Drath",
street: "Gin Blvd",
city: "Austin",
country: "USA",
duns:"123112321",
type: "buyer"
},
{
name: "Asus", // -->COMPANY NAME
email: "Vadar#yahoo.com",
phone: "999-123-8888",
owner: "Vadar",
street: "Vince Blvd",
city: "Dallas",
country: "USA",
duns: "123100000",
type: "supplier"
}];
window.localStorage.setItem("newCompany", JSON.stringify(newCompany));
$scope.companies = [];
var newCompany = JSON.parse(localStorage.getItem("newCompany"));
$scope.companies.push(newCompany[0].name);
You can try with spread
$scope.companies.push(...newCompany.map(item => item.name));
or why do you need exactly push? why don't you just init $scope.companies with exact values
var newCompany = JSON.parse(localStorage.getItem("newCompany"));
$scope.companies = newCompany.map(item => item.name)
If spread is not supported just a regular splice of array can be used
var names = newCompany.map(function(company){return company.name});
$scope.companies.splice(-1, 0, names);
Related
I am trying to turn an array of JavaScript objects into a URL string with params, as seen below:
const objects = [{
firstName: "John",
lastName: "Doe",
age: 46
},
{
country: "France",
lastName: "Paris"
}
]
let entry_arr = [];
objects.forEach(obj => {
Object.entries(obj).forEach(entry => {
entry_arr.push(entry.join('='));
});
});
let entry_str = entry_arr.join('&');
console.log(entry_str);
By all appearances, the above code works. There is a problem though.
The problem
As you can see, I have 2 nested forEach loops. For better performance, I wish I knew how to avoid this nesting and instead use only one forEach loop.
How can I achieve the same result with inly one loop?
Merging each object inside the array in a main one would be the only solution I can think of. ( I assumed lastName: paris was a typo)
const objects = [{
firstName: "John",
lastName: "Doe",
age: 46
},
{
country: "France",
city: "Paris"
}
]
const obj = objects.reduce((acc, obj) => Object.assign(acc, obj), {});
const entry_str = Object.entries(obj).map(entry =>
entry.join('=')
).join('&');
console.log(entry_str);
The answer provided by Nina stil uses a nested loop, instead of using forEach, map is used.
For special character handling i strongly recommend to use the URLSearchParams class.
I would advise to join the array of objects in one single objects with reduce and import the entries in a URLSearchParams
const objects = [
{ firstName: "John", lastName: "Doe", age: 46 }, { country: "France", lastName: "Paris" }];
let reduced = objects.reduce((acc, object) => Object.assign(acc, object))
let params = new URLSearchParams(reduced);
console.log(reduced);
console.log(params.toString());
At least, you need to map the entries with joining key and value and join the nested entries and outer array.
const
objects = [{ firstName: "John", lastName: "Doe", age: 46 }, { country: "France", lastName: "Paris" }],
result = objects
.map(object => Object
.entries(object)
.map(entry => entry.join('='))
.join('&')
)
.join('&');
console.log(result);
object.assign is only perform the direct merge but its not working for nested json.
If anyone worked on this, could you please share the steps.
For example,I want to update the phone number and city of the user. City is under the location property. How should i update the value of city?
Example:
const user = {
name: "Liya",
phone: 12345,
location: {
city: "Camden",
country: "UK"
}
};
const updates = {
name: "David",
phone: 12345678,
location: {
city: "Smithfield"
}
};
Output should be like this:
console.log(Object.assign({}, user, updates));
{
name: 'Liya',
phone: 12345678,
location: {
country: 'UK',
city: 'Smithfield'
}
}
I'm assuming the name should be David since that's the name in the updates.
Based on #Han Moe Htet's comment, I used code from Vincent on that response. I used his because it does not require any external libraries, which Snowflake currently does not allow for Javascript UDFs.
There's an important consideration with this code. It uses recursion, and Snowflake UDFs have rather limited stack depth. If you have a highly nested object, it could run out of stack depth.
set USR = $${
name: "Liya",
phone: 12345,
location: {
city: "Camden",
country: "UK"
}
}$$;
set UPDATES = $${
name: "David",
phone: 12345678,
location: {
city: "Smithfield"
}
}$$;
create or replace function MERGE_OBJECTS("obj1" object, "obj2" object)
returns object
language javascript
strict immutable
as
$$
return merge(obj1, obj2);
function merge(current, updates) {
for (key of Object.keys(updates)) {
if (!current.hasOwnProperty(key) || typeof updates[key] !== 'object') current[key] = updates[key];
else merge(current[key], updates[key]);
}
return current;
}
$$;
with x as
(
select parse_json($USR) as USR, parse_json($UPDATES) as UPDATES
)
select merge_objects(USR, UPDATES) from X;
So say for example I'm making a Social app, and I have a user whom I'm trying to make a group match for
const user = {Name: Stan, location: "Chicago", preferences: {locations: ["New York"]} }
and a collection of people objects like so
const matchPool =
[{Name: Bob, location: "New York", preferences: {locations: ["Chicago"]} },
{Name: Susan, location: "Miami", preferences: {locations: ["Chicago", "Miami"]} },
{Name: Tom, location: "Chicago", preferences: {locations: ["Chicago", "New York"]} },
{Name: Sally, location: "New York", preferences: {locations: ["Chicago", "LA"]} },
{Name: Carl, location: "New York", preferences: {locations: ["Detroit", "LA", "Chicago"]} }]
Say I wanted a group with Stan included, How would I go about filtering so that every member of the group has a location that is in the preferences of every other member of the group?
My first thought was to use lodash with a filter like so
const FilteredPeople = _.filter(matchPool, function(matchCandidate) {
return user.preferences.locations.indexOf(matchCandidate.location) != -1 &&
matchCandidate.preferences.locations.indexOf(user.location) != -1
});
If I add Stan to this group returned we would end up with the following
[{Name: Stan, location: "Chicago", preferences: {locations: ["New York"]}}
{Name: Bob, location: "New York", preferences: {locations: ["Chicago"]}},
{Name: Sally, location: "New York", preferences: {locations: ["Chicago", "LA"]}},
{Name: Carl, location: "New York", preferences: {locations: ["Detroit", "LA", "Chicago"]}}]
Notice the issue is that while Stan is an acceptable match for Bob, Sally, and Carl and vice versa, Bob/Sally/Carl are not acceptable matches for each other because none of them have New York as a location preference.
I realize its not possible from this small data set but given I have a large match pool with many people, how would I filter so that ALL people retuned are both compatible with the seed person(Stan) and each other?
Edit: there was some confusion so to say it another way
The location property is where that person is, the preference location array is the cities where that person is willing to meet other people from, so when we form a group all members need to have a location that is in the preference location array of every other member
See if this does it for you... it just keeps track of where each match is from to make sure we can check others against the current group. I changed Sally's preferences to include New York so she's included in the matches
const user = {Name: 'Stan', location: "Chicago", preferences: {locations: ["New York"]} }
const matchPool =
[{Name: 'Bob', location: "New York", preferences: {locations: ["Chicago"]} },
{Name: 'Susan', location: "Miami", preferences: {locations: ["Chicago", "Miami"]} },
{Name: 'Tom', location: "Chicago", preferences: {locations: ["Chicago", "New York"]} },
{Name: 'Sally', location: "New York", preferences: {locations: ["New York","Chicago"]} },
{Name: 'Carl', location: "New York", preferences: {locations: ["Detroit", "LA", "Chicago"]} }]
let matches=[]
let locs = [user.location]
matchPool.forEach(m=>{
//If a user from the pool matches, add them and also keep track of their location to ensure future matches
if (user.preferences.locations.indexOf(m.location)>-1 && locs.every(val => m.preferences.locations.includes(val))){
matches.push(m)
locs.push(m.location)
}
})
console.log(matches)
const matchPool = [
{Name: 'Bob', location: 'New York', preferences: {locations: ['Chicago']}},
{Name: 'Susan', location: 'Miami', preferences: {locations: ['Chicago', 'Miami']}},
{Name: 'Tom', location: 'Chicago', preferences: {locations: ['Chicago', 'New York']}},
{Name: 'Sally', location: 'New York', preferences: {locations: ['Chicago', 'LA']}},
{Name: 'Carl', location: 'New York', preferences: {locations: ['Detroit', 'LA', 'Chicago']}},
];
const target = {Name: 'Stan',location: 'Chicago',preferences: { locations: ['New York']}};
let matchGroup = matchPool.filter((user) => {
if (
// user in group prefers target's location
user.preferences.locations.includes(target.location) &&
// user's location inside targets prefered locations
target.preferences.locations.includes(user.location)
) {
return user;
}
});
matchGroup = [target, ...matchGroup];
console.log(JSON.stringify(matchGroup, null, 2));
The algorithm could look like this:
Start with a source - filter the db to all items that match. This is the "base-lvl0" (it ensures that our source cannot be ruled out later)
Take the 1. element from the "base-lvl0", and use it as the "source" for a second iteration to produce a "base-lvl1-1"
Take the 2. element from the "base-lvl0", and use it as the "source" for a second iteration to produce a "base-lvl1-2"
Take the 3. element from the "base-lvl0", and use it as the "source" for a second iteration to produce a "base-lvl1-3"
...
n. Take the nth element from the "base-lvl0" and use it as the "source" for a second iteration to produce a "base-lvl1-n"
By the nth step, you'll have a lot of smaller groups that are sure to satisfy at least 2 people. Now, do this with all the "base-lvl1-x" lists to create "base-lvl2-x" lists (to surely satisfy 3 people), then comes "base-lvl3-x", etc. up until all items from all lists have been used as "source".
This way you make sure that in all the FINAL lists everyone is in the preferential lists of everyone. I think this is a bit inefficient but deterministic & sure to satisfy the "location & preferred location" condition.
SUGGESTION:
Try to loosen up the conditions a bit or start to get deep into the beauties of graph theory.
This is quite cutting edge maths, and I think resembles your problem (in some ways): A Breakthrough in Graph Theory - Numberphile (2019)
I am trying to group campaigns in my data by the sales person that created created them but keep going around in circles with different JS array methods.
I have filtered my main data set to return those that have the user role of sales person.
I have my campaign data that shows who created the campaigns
I now have to to group them by sales person.
In my mind I saw it as loop/map through each campaign object in campaigns array, check the createdBy name and return a new array of objects that have the results group by createdBy name.
Sounded easy in my head but can't get around it.
I have put together the following:
const filtered = usersData.filter((val) => val.role === 'sales');
// this returns only the sales people out of all the possible user roles in the following format:
active: true
createdAt: "2019-04-11T21:00:00.000Z"
email: "eliana#example.com"
name: "Alexander Tom Jones"
phone: 3044283743
role: "sales"
_id: "5c8a20d32f8fb814b56fa187"
// my campaign data contains the name of the sales person:
budget: 57154564
company: "sales company"
createdAt: "2020-07-30T09:03:51.925Z"
createdBy: "sales user"
creator_id: "5f228c8d58769fc7d556a6fa"
endDate: "2020-11-08T00:00:00.000Z"
isDeleted: false
location: "Helsinki"
name: "sales test campaign"
// with this function I can return all of the campaigns created by a sales person 1 by 1:
const filteredCampaigns = campaignData.filter(
(val) => val.createdBy === 'sales user'
);
I just cant figure out how to "loop" through each sales person.
I have looked at map / reduce and groupby solutions but nothing comes remotely close. Where am I going wrong?
For grouping by a property, you typically want to use Array.prototype.reduce in a pattern like so:
const bySalesPerson = campaignData.reduce((records, record) => {
// get the property to group by, replace with the
// actual property name you want (createdBy?)
const { salesPerson } = record;
// check if it exists in our accumulator object, if not
// assign empty array
if (!(salesPerson in records)) records[salesPerson] = [];
// push current record into the array associated with
// that value of the property, in this case a particular
// sales person
records[salesPerson].push(record);
// return the accumulator object from the callback
return records;
}, {});
You can use this method to group by sales user. Just call this method like this: const grouped = groupBy(campaignData, ['createdBy']);
groupBy(xs, key) {
return xs.reduce((rv, x) => {
const v = x[key];
const el = rv.find((r) => r && r.key === v);
if (el) {
el.values.push(x);
} else {
rv.push({
key: v,
values: [x]
});
}
return rv;
}, []);
}
Assuming your array contains objects, you can use the filter functionality.
const campaignData = [{
budget: 57154564,
company: "sales company",
createdAt: "2020-07-30T09:03:51.925Z",
createdBy: "sales user",
creator_id: "5f228c8d58769fc7d556a6fa",
endDate: "2020-11-08T00:00:00.000Z",
isDeleted: false,
location: "Helsinki",
name: "sales test campaign"
},
{
budget: 10,
company: "sales company",
createdAt: "2020-07-29T09:03:51.925Z",
createdBy: "buy user",
creator_id: "5f228c8d58769fc7d556a6fb",
endDate: "2020-12-08T00:00:00.000Z",
isDeleted: false,
location: "Stockholm",
name: "sales test campaign"
}
];
const filteredCampaigns = campaignData.filter(
function(item) {
return item.createdBy == 'sales user';
}
);
console.log(filteredCampaigns);
I receive data / an array with objects. each object has country - city and shops (in that city).
For example:
USA - Los Angeles - shop1
Italy - Milan - shop2
Italy - Rome - shopXY
var data = [
{country: "Italy", city: "Milan", shop: "shop123"},
{country: "Italy", city: "Rome", shop: "shop2"},
{country: "USA", city: "Los Angeles", shop: "shopXY"}
]
I have 3 columns and I want to show only once Italy, then when I click on it, I show Milan and Rome, then based on whether I click Rome or Milan the corresponding shops.
Would it be good practise to:
get all the data, then create a new array of objects, so I dont have duplicate countries, cities etc.
Use filter method- but how could I filter it, how can check for duplicates
without storing them in a new array or the like?
Anything else?
I tried to research but couldn't really find anything and even if someone just has some tips, it would be great as I'm totally lost. Thanks!!!!
PS. I don't want to use any filter libraries for that as I m trying to do it myself.
I would recommend using a javascript object, as opposed to making a new array, with the processed data.
The property/value semantics of a Javascript object have following advantages
1.) Duplicates are automatically taken care of: Using the country as a key, you either create a new sub-object mapping shops to cities, or you simply expand an already present one
2.) Ease of access: Finding a Country/shop becomes as simple as data['Italy']['Rome']
Seems like a perfect fit for your use-case. The static way of defining such an object, in adherence to your example woud be:
var data = {
"Italy": {
"Milan": ["shop123"],
"Rome": ["shop2"]
},
"USA": {
"Los Angeles": ["shopXY"]
}
}
MTTI answers is good, and to get to it, I'd use a reduce
const newData = data.reduce((acc, val) => {
if (!acc[val.country]) {
acc[val.country] = { [val.city]: [val.shop] };
return acc;
}
if (!acc[val.country][val.city]) {
acc[val.country][val.city] = [val.shop];
return acc;
}
acc[val.country][val.city].push(val.shop);
return acc;
}, {})
So in the end you'll get an object like
{
Italy: {
Rome: ['Shop123'],
Milan: ['Shop12']
},
USA: {
"San Francisco": ['Shop420']
}
}
You can use the following script to filter the data after that you can iterate on the result of the script to show the data as you want.
var data = [{
country: "Italy",
city: "Milan",
shop: "shop123"
},
{
country: "Italy",
city: "Rome",
shop: "shop2"
},
{
country: "USA",
city: "Los Angeles",
shop: "shopXY"
},
]
var result = {};
data.forEach(function (item) {
if (result[item.country]) {
result[item.country][item.city] = item.shop
} else {
result[item.country] = {};
result[item.country][item.city] = item.shop
}
});
The out put will be like -
{
"Italy": {
"Milan": "shop123",
"Rome": "shop2"
},
"USA": {
"Los Angeles": "shopXY"
}
}