Remove value from Array of Dictionaries - arrays

How I can remove a dict from an array of dictionaries?
I have an array of dictionaries like so: var posts = [[String:String]]() - and I would like to remove a dictionary with a specific key, how would I proceed? I know that I can remove a value from a standard array by doing Array.removeAtIndex(_:) or a dictionary key by doing key.removeValue(), but an array of dictionaries is more tricky.
Thanks in advance!

If I understood you questions correctly, this should work
var posts: [[String:String]] = [
["a": "1", "b": "2"],
["x": "3", "y": "4"],
["a": "5", "y": "6"]
]
for (index, var post) in posts.enumerate() {
post.removeValueForKey("a")
posts[index] = post
}
/*
This will posts = [
["b": "2"],
["y": "4", "x": "3"],
["y": "6"]
]
*/
Since both your dictionary and the wrapping array are value types just modifying the post inside of the loop would modify a copy of dictionary (we created it by declaring it using var), so to conclude we need to set the value at index to the newly modified version of the dictionary

Removing all Dictionaries with a given key
let input = [
[
"Key 1" : "Value 1",
"Key 2" : "Value 2",
],
[
"Key 1" : "Value 1",
"Key 2" : "Value 2",
],
[
"Key 1" : "Value 1",
"Key 2" : "Value 2",
"Key 3" : "Value 3",
],
]
let keyToRemove = "Key 3"
//keep dicts only if their value for keyToRemove is nil (meaning key doesn't exist)
let result = input.filter{ $0[keyToRemove] == nil }
print("Input:\n")
dump(input)
print("\n\nAfter removing all dicts which have the key \"\(keyToRemove)\":\n")
dump(result)
You can see this code in action here.
Removing the only the first Dictionary with a given key
var result = input
//keep dicts only if their value for keyToRemove is nil (meaning key doesn't exist)
for (index, dict) in result.enumerate() {
if (dict[keyToRemove] != nil) { result.removeAtIndex(index) }
}
print("Input:\n")
dump(input)
print("\n\nAfter removing all dicts which have the key \"\(keyToRemove)\":\n")
dump(result)
You can see this code in action here.

Related

JSON schema different for first row and different for remaining rows

my problem statement is :
consider a a list of 15 rows, all rows should have 5 keys. However only the 0th row will have 4 keys. But all the remaining rows will have all the 5 keys.
I want to validate this again my response. Does first and other keyword really exist.
I found this here Correct JSON Schema for an array of items of different type
Example schema
{
"type": "array",
"items": {
"oneOf": [
{
"first": [{
"type": "object",
"required": ["state"],
"properties":{
"state":{
"type":"string"
}
}
}]
},
{
"other": [{
"type": "object",
"required": ["state", "zip"],
"properties":{
"state":{
"type":"string"
},
"zip":{
"type":"string"
}
}
}]
}
]
}
}
First things first: what do you want to achieve with following schema definition?
"first" : [ { ...schema... } ]
As to your problem statement, I am not sure, what you want to achieve:
Schema that allows first array item to be an object with 4 keys, while all other items should have 5 keys?
Schema, that allows only array items=object with 5 keys and will reject a JSON, which does have 4 keys in first item
Could you please rephrase your question to make it more clear? I did some solution basing on assumptions, but it would be good if you could confirm my understanding.
Required reading
Please read first through:
http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.4.1
If "items" is an array of schemas, validation succeeds if each element
of the instance validates against the schema at the same position, if
any.
plus https://stackoverflow.com/a/52758108/2811843 on above topic
https://json-schema.org/understanding-json-schema/reference/array.html#length
https://json-schema.org/understanding-json-schema/reference/array.html#tuple-validation
and https://json-schema.org/understanding-json-schema/reference/array.html in general
as well as
https://json-schema.org/understanding-json-schema/reference/object.html#property-names
https://json-schema.org/understanding-json-schema/reference/object.html#size
and https://json-schema.org/understanding-json-schema/reference/object.html in general.
Possible solution
After looking at sample schema I will rephrase problem statement making some wild assumptions you want a schema, that allows an array of items, where item = object. First item could have 4 keys, while all other items must have 5 keys.
I need a JSON schema that will describe an array of objects, where
first object always has 4 keys/properties, while all remaining objects
do have 5 keys/properties.
Additionally, there is always at least first item in array (containing 4 keys) and there can be up to X other
objects (containing 5 keys) in array.
Go for Tuple-typing and array of objects. Thus you might exactly check that first item (object) has exactly 4 properties and define the schema for the rest of them.
First, full working schema (with comments inside). The "examples" section contains examples of arrays to illustrate the logic, only last 3 will be valid against schema.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "array",
"$comment" : "This is an array, where first item must be an object with at least 4 properties and one property named \"state\" and can contain minimum 1 and maximum of 3 items",
"minItems" : 1,
"maxItems" : 3,
"items": [
{
"type": "object",
"minProperties" : 4,
"required" : ["state"],
}
],
"additionalItems" : {
"$comment" : "Any additional item in this array must be an object with at least 5 keys and two of them must be \"state\" and \"zip\".",
"type" : "object",
"minProperties" : 5,
"required" : ["state", "zip"],
},
"examples" : [
[
{
"key1" : "1",
"key2" : "2",
"key3" : "3",
"state" : "some state",
},
{},
{}
],
[
{
"key1" : "1",
"key2" : "2",
"key3" : "3",
"state" : "some state",
},
{
"key1" : "1",
"key2" : "2",
"key3" : "3",
"state" : "some state",
"zip" : "12345"
},
{
"key1" : "1",
"key2" : "2",
"key3" : "3",
"state" : "some state",
}
],
[
{
"key1" : "1",
"key2" : "2",
"key3" : "3",
"state" : "some state",
},
{
"key1" : "1",
"key2" : "2",
"key3" : "3",
"state" : "some state",
"zip" : "12345"
},
{
"key1" : "1",
"key2" : "2",
"key3" : "3",
"state" : "some state",
"zip" : "54321"
},
{
"key1" : "1",
"key2" : "2",
"key3" : "3",
"state" : "some state",
"zip" : "54321"
}
],
[],
[
{
"key1" : "1",
"key2" : "2",
"key3" : "3",
"state" : "some state",
},
{
"key1" : "1",
"key2" : "2",
"key3" : "3",
"state" : "some state",
"zip" : "12345"
},
{
"key1" : "1",
"key2" : "2",
"key3" : "3",
"state" : "some state",
"zip" : "54321"
},
],
[
{
"key1" : "1",
"key2" : "2",
"key3" : "3",
"state" : "some state",
},
],
[
{
"key1" : "1",
"key2" : "2",
"key3" : "3",
"state" : "some state",
},
{
"key1" : "1",
"key2" : "2",
"key3" : "3",
"state" : "some state",
"zip" : "12345"
},
]
]
}
So, step by step:
"type": "array",
"minItems" : 1,
"maxItems" : 3,
an JSON which is an array with minimum 1 item, maximum 3 items, will be ok. If you don't define "minItems" value, the empty array would pass validation against schema.
"items": [
{
"type": "object",
"minProperties" : 4,
"required" : ["state"],
}
],
This is the Tuple magic - a finite, ordered list of elements (sequence). Yep, maths has it's saying. By using "items" : [ ... ] instead of { ... } you fall into quoted above section of JSON Schema Validation spec (http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.4.1 ).
Above basically says: This is an array, where first item must be an object with at least 4 keys and one of those keys must be "state".
Ok, last but not least:
"additionalItems" : {
"$comment" : "Any additional item in this array must be an object with at least 5 keys and two of them must be \"state\" and \"zip\".",
"type" : "object",
"minProperties" : 5,
"required" : ["state", "zip"],
}
By this I said:
in this array (which must have first item an object with 4 keys and one of those keys is "state" and oh, by the way, an array must have at least 1 item and tops 3 items) you can have additional items on top of the the ones already defined in "items" section. Each such additional item must be an object with at least 5 keys, out of which two must be "state" and "zip".
Does it solve your issue?

Get array key to remove an array based on that array object

New question, so this is the array
[
0: {
"id" : "3"
"name": "David",
"age": "20"
},
1: {
"id" : "6"
"name": "",
"age": "18"
},
2: {
"id" : "8"
"name": "Micheal",
"age": "25"
},
3: {
"id" : "9"
"name": "Wonder Women",
"age": "20"
},
4: {
"id" : "12"
"name": "Clark",
"age": ""
}
]
How to delete based on id when I click a button? In my app have a delete button to delete this array. I think it need to get array key in order to delete the array.
For example: I can get the id=8, but how can i get array key 2 to delete number 2 array?
If you don't understand, please welcome to comment. Thanks.
array.filter((obj) => {
if (obj.id != yourId){
return obj;
}
})
and don't forget all commas in your objects in array. (after id)
if you want to directly manipulate the contents of an array instead of returning new array, you can try this
let index = array.findIndex(obj => obj.id == objIdToDelete)
if(index != -1) { array.splice(index, 1) }
check Array.prototype.splice() to know more
Suppose your array is like:
arr = [
{"id":"3","name":"Clark"},
{"id":"6","name":"David"},
{"id":"8","name":"Miche"}
];
id = 6;
arr = $.grep(arr, function(data, index) {
return data.id != id
});
Now finally this will return array with removing record of id=6
Suppose your array was stored in obj, you can use lodash function remove to remove an item in an array in the following way.
_.remove(obj, function(currentObject) {
return currentObject.id == "8";
});
Which will remove the item '2' containing '8' from your array

how to use for loop make an array which contains something like a dictionary

I want to create an array something like this
array=["1":"1","2":"2","3":"3","4":"4","5":"5","6":"6","7":"7","8":"8"]
It's something like a dictionary, every value needs to be a key:value pair,
so my problem is how to init this type of array? The following is my work, it doesn't work.
array=[String:String]()
for i in 0...7{
array.append(String(i):String(i))
}
every line has a bug!!
plz help
Its not something like Dictionary it is Dictionary, if you want to make a dictionary you can go like this way.
var dictionary = [String:String]()
for i in 0...7{
dictionary[String(i)] = String(i)
}
print(dictionary)
["0":"0","1":"1","2":"2","3":"3","4":"4","5":"5","6":"6","7":"7"]
In addition to Nirav D's answer; I feel the following may help:
There is a method updateValue(_:​for​Key:​) that updates (or adds new key-value pair if the key does not exist) the value for given key.
So your code would look like this:
var array = [String:String]()
for i in 0...7 {
array.updateValue(String(i), forKey: String(i))
}
print(array)
// Output
["2": "2", "1": "1", "6": "6", "4": "4", "3": "3", "7": "7", "0": "0", "5": "5"]
Swift is always amazing you can define += operator that make it easier. So the code will be as follows:
// Defining += operator
func += <K, V> (inout left: [K:V], right: [K:V]) {
for (k, v) in right {
left.updateValue(v, forKey: k)
}
}
// Usage
var array = [String:String]()
for i in 0...7{
array += [String(i):String(i)]
}
print(array)
// Output
["2": "2", "1": "1", "6": "6", "4": "4", "3": "3", "7": "7", "0": "0", "5": "5"]

JQ: Reduce array of objects to object, adding to array

I've got a more complex JQ expression that's handling an array of objects.
The input looks like this:
[
{ "key": "1", "value": "value 1"},
{ "key": "2", "value": "value 2"},
{ "key": "1", "value": "value 3"},
]
What I want to get is this:
{
"1": { "values": ["value 1", "value 3"] },
"2": { "values": ["value 2"] }
}
or, for my use case:
{
"1": [ "value 1", "value 3" ],
"2": [ "value 2" ]
}
would also be OK.
I've already tried to use … | { (.key): [.value] } but the result is (to no real surprise to me) that later occurrences of keys simply overwrite already existing ones. What I want to accomplish is something like "create a new key/value pair or add .value to an already existing one's 'values' array".
The drawback of a solution relying on group_by is that group_by requires a sort, which is unnecessary here. In this response, I'll show how to avoid any sorting by using a generic (and generally useful) jq function that "melds" an array of JSON objects, essentially by popping the value at each key into an array, and then concatenating corresponding arrays.
# input should be an array of objects
def meld:
reduce .[] as $o
({}; reduce ($o|keys)[] as $key (.; .[$key] += [$o[$key]] ));
Let's also define some data:
def data:
[
{ "key": "1", "value": "value 1"},
{ "key": "2", "value": "value 2"},
{ "key": "1", "value": "value 3"}
]
;
Then the filter:
data | map([.] | from_entries) | meld
produces:
{"1":["value 1","value 3"],"2":["value 2"]}
OK, after finally finding out what I wanted I also understand that my previous filters didn't keep the input array but resulted in objects being output after each other. So that was basically the reason why all examples I found wouldn't work.
I wanted to group by keys (hence the key/value requirement), which group_by already does, but wouldn't work.
From grouping working its only a small step to my solution (unique keys, values in arrays).
'… group_by(.key) | map({ "key": .[0].key, "values": map(.value) | unique })'
The output now looks like this, which is perfectly fine for my requirements:
[
{
"key": "1",
"values": [
"value 1",
"value 3"
],
},
{
"key": "2",
"values": [
"value 2"
]
}
]

How to create an array of dictionaries?

new to programming!
I'm trying to create an array of dictionaries inside a struct in Swift like so:
var dictionaryA = [
"a": "1",
"b": "2",
"c": "3",
]
var dictionaryB = [
"a": "4",
"b": "5",
"c": "6",
]
var myArray = [[ : ]]
myArray.append(dictionaryA)
myArray.append(dictionaryB)
This works fine in a playground, but when I put it into an Xcode project, inside a struct, the lines with the append function produce the error "Expected declaration".
I've also tried using the += operator with the same result.
How can I successfully construct this array inside the struct?
From your error Expected declaration, I assume you are doing like:
struct Foo {
var dictionaryA = [
"a": "1",
"b": "2",
"c": "3",
]
var dictionaryB = [
"a": "4",
"b": "5",
"c": "6",
]
var myArray = [[ : ]]
myArray.append(dictionaryA) // < [!] Expected declaration
myArray.append(dictionaryB)
}
This is because you can place only "declarations" in the struct body, and myArray.append(dictionaryA) is not a declaration.
You should do that somewhere else, for example in the initializer. The following code compiles.
struct Foo {
var dictionaryA = [
"a": "1",
"b": "2",
"c": "3",
]
var dictionaryB = [
"a": "4",
"b": "5",
"c": "6",
]
var myArray = [[ : ]]
init() {
myArray.append(dictionaryA)
myArray.append(dictionaryB)
}
}
But as #AirspeedVelocity mentioned, you should provides more information about myArray, or myArray would be Array<NSDictionary> which I think you don't expect.
Anyway, the correct solution would vary depending on what you really trying to do:
Maybe or maybe not, what you want is something like:
struct Foo {
static var dictionaryA = [
"a": "1",
"b": "2",
"c": "3",
]
static var dictionaryB = [
"a": "4",
"b": "5",
"c": "6",
]
var myArray = [dictionaryA, dictionaryB]
}
But, I don't know, why don't you just:
struct Foo {
var myArray = [
[
"a": "1",
"b": "2",
"c": "3",
],
[
"a": "4",
"b": "5",
"c": "6",
]
]
}
The problem lies with this line:
var myArray = [[ : ]]
You need to tell Swift what type myArray is – [[:]] isn’t enough information.
You can either do it the explicit way:
var myArray: [[String:String]] = [[ : ]]
Or, if practical, implicitly using the first or both values you plan to put in:
var myArray = [dictionaryA]
var myArray = [dictionaryA,dictionaryB]
(as an alternative to the explicit empty version, you can also write var myArray = [[String:String]](), which is shorthand for var myArray = Array<Dictionary<String,String>>())
var arrayOfDict = [[String: Int]]()
// Create a dictionary and add it to the array.
var dict1: [String: Int] = ["age": 20]
arrayOfDict.append(dict1)
// Create another dictionary.
var dict2: [String: Int] = ["rank": 5].
arrayOfDict.append(dict2)
// Get value from dictionary in array element 0.
if let value = arrayOfDict[0]["age"] {
print(value)
}
Output
20
Or you can use an array of tuples that´s even easier, like this:
var myArray:[(a:String,b:String,c:String)] = []
And append any element you need later:
self.myArray.append((a:"A",b:"B",c:"c"))
And to use them just:
self.myArray[index].a
self.myArray[index].b
self.myArray[index].c

Resources