Google Earth Engine: set Feature to FeatureCollection, but not a whole Array - arrays

I try to add a new Feature to the large Feature Collection, but with a function set() its override the whole list to each feature. But my purpose is to add each value from the array to the corresponding FeatureCollection. Can anybody help me?
var table = ee.FeatureCollection(ft:.....blablabla);
**//Create an Array from the property DN in the FeatureCollection:**
var propert = table.limit(100).aggregate_array('DN');
*// Values less than 1 will be set to 1, larger than 1== 0:*
var limit = ee.Array(propert).lt(1);
print(limit);
//Function, that add the list! of features (limit) to new property (Class) in the FeatureCollection ("table").
var addFeature = function(ar) {
return ar.set({Class: limit});
//Map throw the Featurecollection table
var areaAdded = table.limit(100).map(addArea);
};
So, if you can see, my code add the whole Array [limit] to each property in the FeatureCollection, not a first Value from the Array to the first property and so on...
Could anybody help me? thank you

If you have a smallish number of features, you can convert the feature collection to a list, convert the array to a list, zip() them together, map a function over the lists to set the property. Toy example:
var features = [
ee.Feature(ee.Geometry.Rectangle(30.01, 59.80, 30.59, 60.15), {name: 'Voronoi'}),
ee.Feature(ee.Geometry.Point(-73.96, 40.781), {name: 'Thiessen'}),
ee.Feature(ee.Geometry.Point(6.4806, 50.8012), {name: 'Dirichlet'})
];
var fromList = ee.FeatureCollection(features);
var array = ee.Array([2, 3, 5]);
var lists = fromList.toList(fromList.size()).zip(array.toList());
var features = ee.FeatureCollection(lists.map(function(l) {
return ee.Feature(ee.List(l).get(0)).set('foo', ee.List(l).get(1));
}));
print(features);

Related

Look for coincidences in two arrays and create another one without the items that are repeated

I am creating an app that gives rewards to the users, so they can obtain randomly complements to their avatars. I have a list of items that they can win and another list of items that they already have. My problem is that I don't know how to look for a match between the two arrays and create another without the ones that they already have.
var availableAvatar =['Csimple','Calien','Ccosmonaut','CgreenAereal','ChappyBirthday']
var userAvatars=['Ccosmonaut','ChappyBirthday']
I tried with the filter method but it creates an array of the matches and I don't know how to do it the other way.
What I need:
var possibleAward=['Csimple','Calien','CgreenAereal']
var random = avatarP[Math.floor(Math.random() * possibleAward.length)];
Thank you very much.
The array filter function is perfect for this:
var availableAvatars = ['Csimple','Calien','Ccosmonaut','CgreenAereal','ChappyBirthday']
var userAvatars = ['Ccosmonaut','ChappyBirthday']
var possibleAvatars = availableAvatars.filter(x => !userAvatars.includes(x));
var randomAvatar = possibleAvatars[Math.floor(Math.random() * possibleAvatars.length)];
console.log(possibleAvatars);
console.log(randomAvatar);
var availableAvatar =['Csimple','Calien','Ccosmonaut','CgreenAereal','ChappyBirthday']
var userAvatars=['Ccosmonaut','ChappyBirthday']
var possibleRewards = availableAvatar.filter(element => {
return !userAvatars.includes(element);
});
console.log(possibleRewards);

How prevent Object.keys() sort?

The problem with the ECMA standard for sort of Object.keys() is known:
Object.keys() handle all keys with integer (example: 168), including integer as strings (example: "168"), as a integer. The result is, both are the same (168 === "168"), and overwrite itself.
var object = {};
object["168"] = 'x';
object[168] = 'y';
Object.keys(object); // Array [ "168" ]
object[Object.keys(object)]; // "y"
Interestingly, all keys (including pure integer keys) are returned as a string.
The ecma262 wrote about this: All keys will be handle as a integer, expect the key is a String but is not an array index.
https://tc39.es/ecma262/#sec-ordinaryownpropertykeys
That should tell us: 168 === "168". A toString() do not solve the problem.
var object = {};
object[[3].toString()] = 'z';
object[[1].toString()] = 'x';
object[[2].toString()] = 'y';
Object.keys(object);
// Array(3) [ "1", "2", "3" ]
Paradoxically, in this case, only integer apply as "enumerable" (it's ignoring array.sort(), that sort also strings with letters.).
My question about this is simple: How can i prevent the sort function in Object.keys()? I have testet the Object.defineProperties(object, 1, {value: "a", enumerable: true/false}), but that mean not realy enumerable in the case of integer or string or integer-like string. It means only should it be counted with or not. It means "counted" like omit (if it false), not "enumerabled" like ascending or descending.
A answere like that is not a good answer: Please use only letters [a-zA-Z] or leastwise a letter at the first position of keyword.
What I want: That the keys are not sorted, but output in the order in which they were entered, whether integer, string or symbol.
Disclaimer: Please solutions only in JavaScript.
Javascript Objects are unordered by their nature. If you need an ordered object-like variable I would suggest using a map.
To achieve what you're looking for with a map instead of object you'd do something like the below:
var map1 = new Map();
map1.set("123", "c");
map1.set(123, "b");
var iterator1 = map1.keys();
var myarray = [];
for (var i = 0; i < map1.size; i++) {
myarray.push(iterator1.next().value);
}
console.log(myarray);
// Array ["123", 123]
Unfortunately it's not compatible with IE and I'm not sure how else you could achieve what you need without it. A quick Google did return something about jQuery maps, though.
If you don't want to use jQuery and still need to support IE some points are below:
Is there anything stopping you using an array rather than JS object to store the data you need? This will retain the order per your requirements unlike objects. You could have an object entry in each iteration which represents the key then use a traditional foreach to obtain them as an array. I.e.
The array:
var test_array = [
{key: 123, value: 'a value here'},
{key: "123", value: 'another value here'}
];
// console.log(test_array);
Getting the keys:
var test_array_keys = [];
test_array.forEach(function(obj) { test_array_keys.push(obj['key']); } );
// console.log(test_array_keys);
Then if you needed to check whether the key exists before adding a new entry (to prevent duplicates) you could do:
function key_exists(key, array)
{
return array.indexOf(key) !== -1;
}
if(key_exists('12345', test_array_keys))
{
// won't get here, this is just for example
console.log('Key 12345 exists in array');
}
else if(key_exists('123', test_array_keys))
{
console.log('Key 123 exists in array');
}
Would that work? If not then the only other suggestion would be keeping a separate array alongside the object which tracks the keys and is updated when an entry is added or removed to/from the object.
Object Keys sorted and store in array
First Creating student Object. then sort by key in object,last keys to store in array
const student={tamil:100, english:55, sci:85,soc:57}
const sortobj =Object.fromEntries(Object.entries(student).sort())
console.log(Object.keys(sortobj))
use map instead of an object.
let map = new Map()
map.set("a", 5)
map.set("d", 6)
map.set("b", 12)
to sort the keys (for example, to update a chart data)
let newMap = new Map([...map.entries()].sort())
let keys = Array.from(newMap.keys()) // ['a','b','d']
let values = Array.from(newMap.values()) // [5,12,6]

How delete object in array Angular JS?

I have an object:
$scope.obj = {
name : "ok",
list : [{object},{object2}]
}
So, I have {object1}. How can I remove this object from list if I dont know key?
My code is:
var indexToDelete = list.people.keys(item);
console.log(indexToDelete);
delete list.people[indexToDelete];
Item is:
Object
$$hashKey:
"object:29"
artist:""
cover:""
song:"Basta 1"
source:""
type:"9"
I'm going to simplify your data structure just a bit, for clarity. I'm also going to assume that the $$hashKey can be used to determine whether the object to be removed is the same as one in the list -- if that's not the case, and we need to compare all the keys and parameters within the objects, the answer gets quite a bit more complex.
Given those assumptions, here is a vanilla javascript version that should work in all current browsers:
var list = [
{$$hashKey: 1, artist: "Alice"},
{$$hashKey: 42, artist: "Bob"},
{$$hashKey: 25, artist: "Charlie"}
];
var itemToRemove = {$$hashKey: 42, artist: "Bob"};
for (var i=0; i<list.length;i++) {
if (list[i].$$hashKey == itemToRemove.$$hashKey) {
list.splice(i,1); // removes the matched element
i = list.length; // break out of the loop. Not strictly necessary
}
}
console.log(list);
You could simplify that somewhat if itemToRemove is a reference to an object that is in the list; in that case you can just compare them directly instead of depending on $$hashKey:
var obj1 = {$$hashKey: 1, artist: "Alice"},
obj2 = {$$hashKey: 42, artist: "Bob"},
obj3 = {$$hashKey: 25, artist: "Charlie"};
var list = [obj1, obj2, obj3];
var itemToRemove = obj2;
for (var i=0; i<list.length;i++) {
if (list[i] === itemToRemove) {
list.splice(i,1); // removes the matched element
i = list.length; // break out of the loop. Not strictly necessary
}
}
console.log(list);
(If you are transpiling from ES6 there are quite a few new convenience methods available so that you don't need to iterate through the array manually: array.prototype.findIndex, array.prototype.filter for example, but these are not currently supported in enough browsers to be usable in production. Alternatively, if you are willing to add a library such as underscore.js, you could use _.without() to remove specific elements.)
Try array splice() method.
The splice() method changes the content of an array by removing existing elements and/or adding new elements.
Working demo :
var obj = {
name : "ok",
list : [
{"name":"abc"},
{"name":"xyz"}
]
}
obj.list.splice(0, 1);
console.log(obj);
There is two case
1. If you have already value as same as you want remove from array then do this
$scope.obj = {
name : "ok",
list : [{object},{object2}]
}
var index =$scope.obj.list.indexOf({object});
$scope.obj.list.splice(index,1);
2. If it is fix that you want to remove first element of array then do this
$scope.obj.list.splice(0,1);
You can make use of the delete keyword and then the property which needs to be deleted.
So, if you need to delete Object1, Firstly, using the findIndex method find the index in the list and then you can use delete.
var indexToDelete = $scope.obj.list.findIndex(YourCriteria);
delete $scope.obj.list[indexToDelete];
Note: findIndex is part of the ES7 Draft specification, so certain browsers might not support this method.
Edit1:
To bring more clarity, the findIndex method takes a callback which is called for each value in the Array.

swift - using .map on struct array

i have a struct array that i want "break up" into smaller arrays that can be called as needed or at least figure out how i can map the items needed off one text value.
the struct:
struct CollectionStruct {
var name : String
var description : String
var title : String
var image : PFFile
var id: String
}
and the array made from the struct
var collectionArray = [CollectionStruct]()
var i = 0
for item in collectionArray {
print(collectionArray[i].name)
i += 1
}
printing partArray[i].name gives the following result:
pk00_pt01
pk00_pt02
pk00_pt03
pk01_pt01
pk01_pt02
pk01_pt03
pk01_pt04
pk01_pt05
pk01_pt06
pk01_pt07
pk01_pt08
this is just some test values but there could be thousands of entries here so i wanted to filter the entire array just by the first 4 characters of [i].name i can achieve this by looping through as above but is this achievable using something like .map?
I wanted to filter the entire array just by the first 4 characters of
[i].name
You can achieve this by filtering the array based on the substring value of the name, as follows:
let filteredArray = collectionArray.filter {
$0.name.substring(to: $0.name.index($0.name.startIndex, offsetBy: 4)).lowercased() == "pk00"
// or instead of "pk00", add the first 4 characters you want to compare
}
filteredArray will be filled based on what is the compared string.
Hope this helped.
If you want to group all data automatically by their name prefix. You could use a reducer to generate a dictionary of grouped items. Something like this:
let groupedData = array.reduce([String: [String]]()) { (dictionary, myStruct) in
let grouper = myStruct.name.substring(to: myStruct.name.index(myStruct.name.startIndex, offsetBy: 4))
var newDictionart = dictionary
if let collectionStructs = newDictionart[grouper] {
newDictionart[grouper] = collectionStructs + [myStruct.name]
} else {
newDictionart[grouper] = [myStruct.name]
}
return newDictionart
}
This will produce a dictionary like this:
[
"pk00": ["pk00_pt01", "pk00_pt02", "pk00_pt03"],
"pk01": ["pk01_pt01", "pk01_pt02", "pk01_pt03", "pk01_pt04", "pk01_pt05", "pk01_pt06", "pk01_pt07"],
"pk02": ["pk02_pt08"]
]
Not sure if i am understanding you correctly but it sounds like you are looking for this...
To create a new array named partArray from an already existing array named collectionArray (that is of type CollectionStruct) you would do...
var partArray = collectionArray.map{$0.name}

How to reference a child array based on the parent array's key?

I have the following dictionary:
var deckDictionary = [
"card1": ["ace","hearts"],
"card2": ["ace","spades"],
"card3": ["ace","diamonds"],
"card4": ["ace","clubs"],
]
What I want to do is set cardSuit2 to be equal to the 2nd object in the array with key "card2" like so (pseudo-code):
var cardKey2 = "card2"
var cardSuit2 = whatever the card suit value is at cardKey2 ([[deckDictionary[1]][1]]?)
So for instance in this case, cardSuit2 would be equal to the 2nd object in the array with key "card2", so "spades". How would I go about doing this?
If you just want to get the value of the element that is pointed out in the question it is possible to do so:
var cardKey2 = "card2"
var cardSuit2 = deckDictionary[cardKey2]?.last

Resources