I am attempting to push one index of my array into it's own array. I am attempting this by using the forEach() method.
I have an array that is nested inside of an array revData that has multiple indexes inside of its array. I expecting to push out only index 5 of the array into its own array so I can graph the data.
At the moment using doing my forEach method, my newArr only has the first index 5 five times.
My expected out come is to have the newArr have 3 results coming from the values of index 5 from revData such as :
newArr = [ 24343.1 , 44321.0, 43242.8 ]
Here is an example of my code :
let revData = [
[1, 1, 1, "22", "online stores", 24343.1 ],
[2, 2 ,2, "13", "retail stores", 44321.0],
[ 3, 3, 3, "7", "walk ins", 43242.8]
]
const newArr = []
revData[0].forEach(function () {
newArr.push(revData[0][5])
})
console.log(newArr)
Probably it should be like this
let revData = [
[1, 1, 1, "22", "online stores", 24343.1],
[2, 2, 2, "13", "retail stores", 44321.0],
[3, 3, 3, "7", "walk ins", 43242.8],
];
const newArr = [];
revData.forEach(function (child) {
newArr.push(child[5]);
});
console.log(newArr);
Or you can use map instead
const newArr = revData.map((child) => child[5]);
console.log(newArr);
You are iterating over revData[0] so you won't get the other items. Also, during the iteration you always read the value in revData[0]. You should use the first parameter of the forEach callback, like this:
let revData = [
[1, 1, 1, "22", "online stores", 24343.1],
[2, 2, 2, "13", "retail stores", 44321.0],
[3, 3, 3, "7", "walk ins", 43242.8]
]
const newArr = []
revData.forEach(function(item) {
newArr.push(item[5])
})
console.log(newArr)
One available approach here is to use a for... of loop.
Everyone will have their own preferred approach, but I generally find that, for syntactic clarity, I favour for...of loops over forEach.
Working Example:
let revData = [
[1, 1, 1, "22", "online stores", 24343.1 ],
[2, 2 ,2, "13", "retail stores", 44321.0],
[3, 3, 3, "7", "walk ins", 43242.8]
];
const newArr = [];
for (arrayElement of revData) {
newArr.push(arrayElement[5]);
}
console.log(newArr);
The language here is a little off and I'll do my best to answer.
When you say "push out" I am assuming you want to remove the element out of the array. The correct term for removing an element from the array is "pop". "Pop" is generally related to removing an element an array, while "push" is generally related to adding an element to an array.
Also Do not name your newArr as a const. const is meant to indicate values that never change. By naming your newArr as a const, it cannot change.
Now to answer your question, I can see what you are trying to do, but your syntax is a little wrong.
let revData = [
[1, 1, 1, "22", "online stores", 24343.1 ],
[2, 2 ,2, "13", "retail stores", 44321.0],
[ 3, 3, 3, "7", "walk ins", 43242.8]
]
let newArr = []
revData.forEach(function(item) {
newArr.push(item[5])
})
console.log(newArr)
https://codepen.io/junghole/pen/BajdZPq?editors=0012
I suggest that you gain a better understanding of 2d arrays and for each loops. A good resource is geeks for geeks, or simply googling. Good Luck!
Related
I am searching for an algorithm to reorder an list of dictionarys or in javascript array of objects.
For example I have the following list of objects:
my_dict = [
{
"id": 123,
"priority": 1
},
{
"id": 234,
"priority": 2
},
{
"id": 345,
"priority": 3
},
{
"id": 654,
"priority": 4
}
]
Now I want to change the item with id 654 to be the first priority. So the other items gets automatically to priority 2,3 and 4.
This should be the result:
my_dict = [
{
"id": 654,
"priority": 1
}
{
"id": 123,
"priority": 2
},
{
"id": 234,
"priority": 3
},
{
"id": 345,
"priority": 4
},
]
Another example is when I want to decrease the priority of item 234 to priority 3 then the item with priority 3 should become priority 2 (from the original/first dict). There are should no priority be twice in this list and there should not be gaps.
my_dict = [
{
"id": 123,
"priority": 1
},
{
"id": 345,
"priority": 2
},
{
"id": 234,
"priority": 3
},
{
"id": 654,
"priority": 4
}
]
For clarification here is an other example.
If I move item with id 123 to priority 4 the item before should become priority 1,2 and 3.
my_dict = [
{
"id": 234,
"priority": 1
},
{
"id": 345,
"priority": 2
},
{
"id": 654,
"priority": 3
}
{
"id": 123,
"priority": 4
},
]
The list should always start with priority 1. Can somebody explain how I can implement it with python or javascript? I tried it with a for loop starting and 1 but this does not work.
The discussions about a better data structure are spot-on. But if you still want to implement what you asked for, we can write a straightforward JS version that does the naive thing:
const changePriority = (xs, id, to,
idx = xs .findIndex (({id: i}) => i == id),
ys = [...xs .slice (0, idx), ...xs .slice (idx + 1)]
) =>
[ ...ys . slice (0, to - 1), xs [idx], ...ys .slice(to - 1)]
.map ((x, i) => ({...x, priority: i + 1}))
const dict = [{id: 123, priority: 1}, {id: 234, priority: 2}, {id: 345, priority: 3}, {id: 654, priority: 4}]
console .log (
changePriority (dict, 654, 2)
)
.as-console-wrapper {max-height: 100% !important; top: 0}
Note that this depends upon your id and the new priorty, to actually existing in the input. It wouldn't be hard to add error-checking.
Also note that this returns a new array, and doesn't mutate the original; we're not barbarians here.
I disagree with the idea of having priority be represented by both the position in the list and the "priority" member. This is redundant and will cause trouble at some point.
Further, I have to make assumptions to answer this question, as the question is not complete.
Assumptions:
In the end, the list should be sorted by priority again
Priorities should end up being integers
Priorities always start at 1 and enumerate the list without gaps
First approach
Specify exactly where you want to put your item by using halfs. This is simple and everything else should fall in place.
Example
Task: Move 234 to priority 3.
Sadly, it is not uniquely defined what this is supposed to mean, as it is unclear where the old item of priority 3 should move to.
Instead move it to priority 3.5 to make it unambiguous, then re-sort and re-enumerate:
# Change priority of '234' to '3.5'
my_dict[1]["priority"] = 3.5
# Sort
my_dict.sort(key=lambda x: x["priority"])
# Re-enumerate
for (position, item) in enumerate(my_dict):
item["priority"] = position + 1
print(my_dict)
[{'id': 123, 'priority': 1}, {'id': 345, 'priority': 2}, {'id': 234, 'priority': 3}, {'id': 654, 'priority': 4}]
For large datasets this is really slow though, as every single priority change is O(n*log(n)), as it requires a sort.
You should investigate in better data structures, like a heap or a linked list, depending on your exact usage scenario.
Second approach
If we remove the 'priority' member, we can write a much more efficient algorithm:
def move(data, original, target):
data.insert(target, data.pop(original))
# Important: Start priorities at 0, not 1. This makes this a lot easier.
my_dict = [123, 234, 345, 654]
move(my_dict, 3, 0)
print(my_dict)
my_dict = [123, 234, 345, 654]
move(my_dict, 1, 2)
print(my_dict)
[654, 123, 234, 345]
[123, 345, 234, 654]
https://ideone.com/o9UcCb
For a longer discussion about how to move an item inside of a list, read this discussion.
I have an array of objects that looks like this:
[
{
"id": 123,
"timeStamp": "\"2019-07-08T20:36:41.580Z\"",
"data": [1, 2, 3]
},
{
"id": 234,
"timeStamp": "\"2019-07-08T20:37:12.472Z\"",
"data": ["Apples", "Oranges"]
}
]
I want to update the value of a particular property of an object within the array but also want to make sure that I return the result in a new array.
How do I do this without running through some type of a loop e.g. for loop?
Say, I want to update the data property of the second object and add Bananas to it.
If you want the result to be a new array, you'll first have to clone the array. This can be more complicated than you might imagine (depending on how deeply you wish to clone things). One way is to use JSON stringify...
Bear in mind that the JSON trick is effectively doing a loop behind the scenes. Inevitable if you want to copy the array, really.
To find the object by ID use Array.find()
let original = [
{
"id": 123,
"timeStamp": "\"2019-07-08T20:36:41.580Z\"",
"data": [1, 2, 3]
},
{
"id": 234,
"timeStamp": "\"2019-07-08T20:37:12.472Z\"",
"data": ["Apples", "Oranges"]
}
]
let copy = JSON.parse(JSON.stringify(original));
copy.find(obj => obj.id === 234).data.push("Bananas");
console.log(copy);
Something like this would do the trick:
let arr = [
{
"id": 123,
"timeStamp": "\"2019-07-08T20:36:41.580Z\"",
"data": [1, 2, 3]
},
{
"id": 234,
"timeStamp": "\"2019-07-08T20:37:12.472Z\"",
"data": ["Apples", "Oranges"]
}
]
arr[1]['data'] = [...arr[1]['data'], 'Bananas']
console.log(arr)
For your example: you can do something like this: say your array of object is saved in test variable
test[1].data.push("Bananas")
please suggest elegant ways to sort an array by data types.
For example, sorting the following array:
testArray = ["1", "5", 4 , 8, [1,2,3], {test:"test"}, [1,3,4], {test2:"test2"}, 6, "test"]
to appear like that:
["1", "5", "test", 4, 6, 8, [1,2,3], [1,3,4], {test:"test"}, {test2:"test2"}]
The actual order of the datatypes doesn't really matter.
Thanks!
If you don't have to worry about certain edge cases like undefined and null, you could use value.constructor.name.
This will sort values by type "Array", "Number", "Object", "String", in that order:
const input = ["1", "5", 4 , 8, [1,2,3], {test:"test"}, [1,3,4], {test2:"test2"}, 6, "test"];
const sorted = input.sort((a, b) => (a.constructor.name).localeCompare(b.constructor.name));
console.log(JSON.stringify(sorted));
I'm practicing how to maniupulate data in JS in this article: http://learnjsdata.com/combine_data.html
var articles = [
{"id": 1, "name": "vacuum cleaner", "weight": 9.9, "price": 89.9, "brand_id": 2},
{"id": 2, "name": "washing machine", "weight": 540, "price": 230, "brand_id": 1},
{"id": 3, "name": "hair dryer", "weight": 1.2, "price": 24.99, "brand_id": 2},
{"id": 4, "name": "super fast laptop", "weight": 400, "price": 899.9, "brand_id": 3}
];
var brands = [
{"id": 1, "name": "SuperKitchen"},
{"id": 2, "name": "HomeSweetHome"}
];
articles.forEach(function(article) {
var result = brands.filter(function(brand){
return brand.id === article.brand_id;
});
delete article.brand_id;
article.brand = (result[0] !== undefined) ? result[0].name : null;
});
I'm confused with the last part: article.brand = (result[0] !== undefined) ? result[0].name : null;
I understand the conditional operation: it wants to have null value if result[0] is not defined. But I'm wondering what result[0] refers to. I thought it would take first object: {"id":2, "name": "HomeSweetHome"} so there should be for loop to iterate all objects in order to see if objects meet the condition? Could you inform me what I'm missing or/and what result[0] refers to?
Thanks,
result[0] will be undefined in case there is no element in result. result is expected to be an array of brands filtered by the filter operation
The filtered array result will have same brand as that of the current article in the outer foreach loop. The filter condition is going to achieve that.
It looks like in this particular case you will get only one element in result array always as there are unique brand ids. It might have more elements in case of duplicated brand ids.
result[0] points to first element in the array result
How does underscorejs reduce work?
It's simple to get
_.reduce([1, 2, 3], function(memo, num){ return memo + num; }, 0); (the result is 6).
But how do the other optional parameters work? In the docs it says:
Memo is the initial state of the reduction, and each successive step of it should be returned by iterator. The iterator is passed four arguments: the memo, then the value and index (or key) of the iteration, and finally a reference to the entire list."
But I don't understand. I tried to use reduce for the following problem, and I couldn't figure it out:
var input = [{"score": 2, "name": "Jon", "venue": "A"}, {"score": 3, "name": "Jeff", "venue":"A"}, {"score": 4, "name": "Jon", "venue":"B"}, {"score": 4, "name": "Jeff", "venue":"B"}];
var output = [{"score": 6, "name":"Jon", "venue": ["A", "B"]}, {"score": 7, "name":"Jeff", "venue": ["A", "B"]}];
How can I get as output using _reduce for input? And it will really helpful how it works inside reduce.
Reduce takes a list of values, and reduces it to a single value. What you are trying is not just reduce. You are trying to first group (by name) and then reduce each group. A possible implementation would be something like this, where you first group, and then map each group to a reduce operation that accumulates the score and appends the venue.
var input = [
{"score": 2, "name": "Jon", "venue": "A"},
{"score": 3, "name": "Jeff", "venue":"A"},
{"score": 4, "name": "Jon", "venue":"B"},
{"score": 4, "name": "Jeff", "venue":"B"}];
var output = _.map(_.groupBy(input, "name"), function(group, name) {
return _.reduce(group, function(memo, elem) {
memo.score += elem.score;
memo.venue.push(elem.venue);
return memo;
},
{ name: name, score: 0, venue: [] });
});
Instead of reduce, try using plain and simple each in this way:
_.each admits a third parameter for a context. So, for example:
var input = ["Alice", "Bob", "Charlie"];
var context = {};
_.each(input, function(o,i) { this[i] = o; }, context);
console.log(context) //=> {1: "Alice", 2: "Bob", 3: "Charlie"}
Ruby has a new method call each_with_object similar to reduce for that exact pattern, where the memo is not necessarily the value return (in fact, my function is not returning anything!); but underscore simplifies its API design simply admitting a context for the function as the third parameter.
You can use reduce, but you would need to return the memo each time, making it a bit less elegant IMHO.