I have a 2D array with multiples values.
One field on this array is called group, let's imagine my array have this order:
private var myArray = [
ArrayModel(
id: 0,
name: "Test",
color: 0,
img: "img.png",
group = "myGroup"),
ArrayModel(
id: 1,
name: "Test1",
color: 0,
img: "img.png",
group: "myGroup"),
ArrayModel(
id: 2,
name: "Test2",
color = 0,
img = "img.png",
group = "myGroup3")
ArrayModel(
id: 3,
name: "Test3",
color: 0,
img: "img.png",
group: "myGroup2"),
ArrayModel(
id: 4
name: "Test4"
color: 0
img: "img.png"
group: "myGroup3")
]
Array Model
class ArrayModel: Decodable {
var id: Int
var name: String
var color: Int
var img: String
var group: String
convenience init() {
self.init()
id = 0
name = ""
color = 0
img = ""
group = ""
}
init(id: Int, name: String, color: Int, img: String, group: String) {
self.id = id
self.name = name
self.color = color
self.img = img
self.group = group
}
}
How can I move my myArray[2] to be in myArray[1] ?
My desired output is :
let myArray = [
ArrayModel(
id: 0,
name: "Test",
color: 0,
img: "img.png",
group: "myGroup")
]
[1] => same shema, but group => "myGroup"
[2] => same shema, but group => "myGroup2"
[3] => same shema, but group => "myGroup2"
[4] => same shema, but group => "myGroup3"
]
I tried this :
myArray.sorted(by: { $0.group < $1.group })
Thanks for your help!
Try this:
myArray.sort { $0.group < $1.group }
The .sort(by: ...) isn't what you need here, as you want to modify myArray (by sorting it). To do that, you have to omit the by:....
For more information, see this answer :)
This may help you to sorted by Case Sensitive but your myArray should be mutable. ex : var myArray
myArray = myArray.sorted(by: { $0.group.localizedCompare($1.group) == .orderedAscending})
Related
I have the following tow arrays:
fetchedProducts = [
[name: "productName20", id: 20],
[name: "productName3", id: 3],
[name: "productName1", id: 1]
]
sortedProducts = [
[productName1: "1"], // I know the numbers here are string; I need them to be string
[productName20: "20"],
[productName3: "3"]
]
Now I need to sort fetchedProducts based on the order of sortedProducts so it would end up looking like the following:
fetchedProducts = [
[name: "productName1", id: 1],
[name: "productName20", id: 20],
[name: "productName3", id: 3]
]
You can try the following in Swift. Note the dictionaries in Swift are unordered so you have to use arrays for ordered collections:
let fetchedProducts = [
(name: "productName20", id: 20),
(name: "productName3", id: 3),
(name: "productName1", id: 1),
]
let sortedProducts = [
("productName1", "1"),
("productName20", "20"),
("productName3", "3"),
]
let sortedFetchedProducts = sortedProducts
.compactMap { s in
fetchedProducts.first(where: { s.1 == String($0.id) })
}
print(sortedFetchedProducts)
// [(name: "productName1", id: 1), (name: "productName20", id: 20), (name: "productName3", id: 3)]
JavaScipt realisation:
const fetchedProducts = [
{name: "productName20", id: 20},
{name: "productName3", id: 3},
{name: "productName1", id: 1}
];
const sortedProducts = [
{productName1: "1"}, // I know the numbers here are string; I need them to be string
{productName20: "20"},
{productName3: "3"}
];
const sortProducts = (fetchedProducts, sortedProducts) => {
// Extract ordered id from the sortedProducts array
const orderIds = sortedProducts.map(sorted => +Object.values(sorted));
// Find product by sorted id and put into new array
const sortedFetchedProducts = [];
orderIds.forEach(id => {
let product = fetchedProducts.find(item => item.id === id);
sortedFetchedProducts.push(product);
});
return sortedFetchedProducts;
}
const sortedFetchedProducts = sortProducts(fetchedProducts, sortedProducts);
console.log(sortedFetchedProducts);
Output:
[
{ name: 'productName1', id: 1 },
{ name: 'productName20', id: 20 },
{ name: 'productName3', id: 3 }
]
Considering these two objects :
struct Product {
let id: Int
let title: String
let price: Int
let categoryId: Int
}
struct Category {
let id: Int
let name: String
}
And these two object arrays :
let products = [
Product(id: 1, title: "snake", price: 20, categoryId: 1),
Product(id: 2, title: "soap", price: 20, categoryId: 2),
Product(id: 3, title: "cream", price: 20, categoryId: 3),
Product(id: 4, title: "dog", price: 20, categoryId: 1),
Product(id: 5, title: "car", price: 20, categoryId: 4),
]
let categorieItems = [
Category(id: 1, name: "animal"),
Category(id: 2, name: "chemichal"),
Category(id: 3, name: "food"),
Category(id: 4, name: "travel"),
]
How can I handle these two structures to assign in the cellForRowAt indexPath tableView method the product title property to cell.textLabel?.text and the corresponding category name (linked with the categoryId property) contained in categorieItems to the cell.detailTextLabel?.text
For example :
cell.textLabel?.text = snake
cell.detailTextLabel?.text = animal
You can have a function that takes category id and return category from categorieItems
like
private func getCategoryForID(_ categoryId: Int) -> Category {
categorieItems.filter { $0.id == categoryId }
}
Supposing I have these two objects :
struct Product {
let id: Int
let title: String
let price: Int
let categoryId: Int
}
struct Category {
let id: Int
let name: String
}
Then I create two arrays containing those objects :
let products = [Product(id: 1, title: "snake", price: 20, categoryId: 1),
Product(id: 2, title: "soap", price: 20, categoryId: 2),
Product(id: 3, title: "cream", price: 20, categoryId: 3),
Product(id: 4, title: "dog", price: 20, categoryId: 1),
Product(id: 5, title: "car", price: 20, categoryId: 4),
]
let categorieItems = [Category(id: 1, name: "animal"),
Category(id: 2, name: "chemichal"),
Category(id: 3, name: "food"),
Category(id: 4, name: "travel"),
]
I want to create a new array which contains the names of all the product categories :
func handleCategories() -> [String] {
var categoryNames = [String]()
for product in products {
for categorieItem in categorieItems {
if product.categoryId == categorieItem.id {
categoryNames.append(category.name)
}
}
}
return categoryNames
}
This method works but I want to write one with closure (I guess map() should works)
The result should be :
categoryNames = ["animal", "chemichal", "food", "animal", "travel"]
Make a dictionary that keys the category by id, and map each product into a category by looking up its categoryId in that dict.
I used a force unwrap, assuming that products don't contain any invalid categoryIds.
struct Product {
let id: Int
let title: String
let price: Int
let categoryId: Int
}
struct Category {
let id: Int
let name: String
}
let products = [
Product(id: 1, title: "snake", price: 20, categoryId: 1),
Product(id: 2, title: "soap", price: 20, categoryId: 2),
Product(id: 3, title: "cream", price: 20, categoryId: 3),
Product(id: 4, title: "dog", price: 20, categoryId: 1),
Product(id: 5, title: "car", price: 20, categoryId: 4),
]
let categorieItems = [
Category(id: 1, name: "animal"),
Category(id: 2, name: "chemichal"),
Category(id: 3, name: "food"),
Category(id: 4, name: "travel"),
]
let categoriesById = Dictionary(uniqueKeysWithValues:
categorieItems.map { (key: $0.id, value: $0) }
)
let productCategoryNames = products.map { categoriesById[$0.categoryId]!.name }
print(productCategories)
Supposed we have this
oldArray = [
{ id: 1, position: 'DEV OM'},
{ id: 2, position: 'Senior Developer'},
]
newArray = [
{ id: 2, position: 'Senior Developer'},
{ id: 3, position: 'Junior Developer'},
]
Now how can we get the removed and added items in those arrays?
addedItems = getAddedItems(oldArray, newArray)
removedItems = getRemovedItems(oldArray, newArray)
// Output for addedItems
[
{ id: 3, position: 'Junior Developer'}
]
// Output for removedItems
[
{ id: 1, position: 'DEV OM'}
]
Im using typescript/angular2 app
What you need is a function to find the difference between 2 arrays:
let oldArray = [
{ id: 1, position: 'DEV OM'},
{ id: 2, position: 'Senior Developer'}
]
let newArray = [
{ id: 2, position: 'Senior Developer'},
{ id: 3, position: 'Junior Developer'}
]
function difference(a,b) {
return a.filter(itema => !b.some(itemb => itemb.id===itema.id));
}
console.log(difference(oldArray,newArray))
console.log(difference(newArray,oldArray))
How to remove item from array B if array A has it. I want to iterate through by ID.
array A: it has all the items
[{
"Name":"John",
"Id":1
},
{
"Name":"Peter",
"Id":2
},
{
"Name":"Phillip",
"Id":3
},
{
"Name":"Abby",
"Id":4
},
{
"Name":"Don",
"Id":5
}]
array B: has just the selected items
[{
"Name":"John",
"Id":1
},
{
"Name":"Abby",
"Id":4
}]
I want to remove from array A John and Abby by Id, because they are in array b.
for (var i = 0; i < a.length; i++) {
if (b[i].Id == ta[i].Id) {
for (var j = 0; j < b[j]; j++) {
a.splice(i, 1);
}
}
}
this is not working as I thought
You could first get all id's of person objects in b:
let idsInB: number[] = b.map(person => person.Id); // > [1, 4]
This array of id's can be used to filter a, and then assign the result back to a. Let's contain that in a function cleanA:
function cleanA(): void {
let idsInB: number[] = b.map(person => person.Id);
a = a.filter((person) => -1 === idsInB.indexOf(person.Id));
}
All you need to do now is call cleanA whenever the contents of b changes.
Full working example:
interface Person {
Id: number;
Name: string;
}
let a: Person[] = [
{ Id: 1, Name: "John" },
{ Id: 2, Name: "Peter" },
{ Id: 3, Name: "Phillip" },
{ Id: 4, Name: "Abby" },
{ Id: 5, Name: "Don" },
];
let b: Person[] = [
{ Id: 1, Name: "John" },
{ Id: 4, Name: "Abby" },
];
function cleanA(): void {
let idsInB: number[] = b.map(person => person.Id);
a = a.filter((person) => -1 === idsInB.indexOf(person.Id));
}
presentArray(a, 'A before clean');
cleanA();
presentArray(a, 'A after clean');
// -------------------------------------------------------
// Displaying purposes only:
// -------------------------------------------------------
function presentArray(arr, msg) {
document.body.innerHTML += `<br><b>${msg}:</b><br>[<br>`
+ arr.map(person => ` { Id: ${person.Id}, Name: ${person.Name} },<br>`)
.join('')
+ ' ]<br><br>';
}