How to combine elements in an array? - arrays

I'm trying to combine the "role" parameter for "Project" objects with the same "id" and "title" parameters in the myProjects array below:
struct Project: Identifiable {
var id: String
var title: String
var role: String
}
var myProjects = [Project(id: "1", title: "Sunset", role: "2nd AD"),
Project(id: "2", title: "Lights", role: "Mix Tech"),
Project(id: "2", title: "Lights", role: "Sound Mixer"),
Project(id: "3", title: "Beach", role: "Producer")]
var updatedProjects: [Project] = []
// The goal is to update myProjects to show the following:
updatedProjects = [Project(id: "1", title: "Sunset", role: "2nd AD"),
Project(id: "2", title: "Lights", role: "Mix Tech & Sound Mixer"),
Project(id: "3", title: "Beach", role: "Producer"]
This is what I have attempted so far, the result is giving me duplicate combinations of the roles parameter for each project in the myProjects array.
var dupProjects = myProjects
for myProject in myProjects {
for dupProject in dupProjects {
if myProject.id == dupProject.id {
let combinedRoles = "\(myProject.role) & \(dupProject.role)"
updatedProjects.append(Project(id: myProject.id,
title: myProject.title,
role: combinedRoles))
}
}
}
print(updatedProjects)
// [__lldb_expr_48.Project(id: "1", title: "Sunset", role: "2nd AD & 2nd AD"),
__lldb_expr_48.Project(id: "2", title: "Lights", role: "Mix Tech & Mix Tech"),
__lldb_expr_48.Project(id: "2", title: "Lights", role: "Mix Tech & Sound Mixer"),
__lldb_expr_48.Project(id: "2", title: "Lights", role: "Sound Mixer & Mix Tech"),
__lldb_expr_48.Project(id: "2", title: "Lights", role: "Sound Mixer & Sound Mixer"),
__lldb_expr_48.Project(id: "3", title: "Beach", role: "Producer & Producer")]

You can use a dictionary to group them by id, combine the roles, then convert the group back to a single Project
let combined = Dictionary(grouping: myProjects) { element in
return element.id
}.compactMapValues { projects -> Project? in
var first = projects.first
first?.role = projects.map { $0.role }.joined(separator: " & ")
return first
}.values.map { $0 }

Related

Display specific flastlist items with specific keys

my data :
const DATA = [
{
id: "1",
from: "Canada",
name: "person1",
},
{
id: "2",
from: "Canada",
name: "person2",
},
{
id: "3",
from: "France",
name: "person3",
}];
i need to filter this flatList and only display people from Canada
I think you are looking for something like:
const result = DATA.filter(element=> element.from === "Canada")
Then you can use your result to display it in the format that you want.

Swift how to filter 2 array

I'm new in Swift, and I can't figure out how to filter these 2 arrays
var arrayOfFavoriteRoomsId = ["1", "2"]
var arrayOfRooms = [
VoiceRoom(id: "1", title: "Room1", description:"Test room1"),
VoiceRoom(id: "2", title: "Room2", description:"Test room2"),
VoiceRoom(id: "3", title: "Room3", description:"Test room3")
]
The final array should look like this
var filteredArray = [
VoiceRoom(id: "1", title: "Room1", description:"Test room1"),
VoiceRoom(id: "2", title: "Room2", description:"Test room2")
]
This is what my model looks like
struct VoiceRoom: Identifiable, Decodable {
var id: String
var title: String
var description: String
}
arrayOfRooms.filter { room in
arrayOfFavoriteRoomsId.contains(room.id)
}
If you want to sort them as well:
arrayOfRooms.filter { room in
arrayOfFavoriteRoomsId.contains(room.id)
}.sorted(by: { $0.id < $1.id })

Dynamically merge array objects

I want to combine two arrays (ranking and matches) that has common properties:
var ranking = [{
def: "0.58",
league: "Scottish Premiership",
name: "Celtic",
off: "3.33",
grank: "3",
tform: "96.33",
},
{
def: "2.52",
league: "Scottish Premiership",
name: "Dundee",
off: "1.28",
grank: "302",
tform: "27.51",
}]
var matches = [{
date: "2010-04-22",
league: "Scottish Premiership",
home: "0.0676",
away: "0.8",
draw: "0.1324",
goals1: "3",
goals2: "1",
tform1: "96.33",
tform2: "27.51",
team1: "Celtic",
team2: "Dundee",}]
Expected output looks like this:
[{
date: "2010-04-22",
league: "Scottish Premiership",
home: "0.0676",
away: "0.8",
draw: "0.1324",
goals1: "3",
goals2: "1",
tform1: "96.33",
tform2: "27.51",
def1: "0.58",
def2: "2.52",
off1: "3.33",
off2: "1.28",
grank1: "3",
grank2: "302",
team1: "Celtic",
team2: "Dundee",}]
To merge the arrays, I used Lodash _.merge function
var result = _.merge(ranking, matches);
The output it returned did merge some objects and omitted homogeneous objects.
Please I need some help and insight in achieving this task. I wouldn't mind any javascript (client-side) solution.
You need to merge by the given data and add the information of the two teams.
const
keys = ['def', 'off', 'grank'],
getRanking = (team, suffix) => Object
.fromEntries(keys.map(k => [k + suffix, team[k]])),
ranking = [{ def: "0.58", league: "Scottish Premiership", name: "Celtic", off: "3.33", grank: "3", tform: "96.33" }, { def: "2.52", league: "Scottish Premiership", name: "Dundee", off: "1.28", grank: "302", tform: "27.51" }],
matches = [{ date: "2010-04-22", league: "Scottish Premiership", home: "0.0676", away: "0.8", draw: "0.1324", goals1: "3", goals2: "1", tform1: "96.33", tform2: "27.51", team1: "Celtic", team2: "Dundee" }],
teams = Object.fromEntries(ranking.map(o => [o.name, o])),
result = matches.map(o => ({
...o,
...getRanking(teams[o.team1], 1),
...getRanking(teams[o.team2], 2)
}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sort Array in Array

I have following array result:
Example:
[
{
id: "1",
league: {
name: "World Club Friendlies",
team: "Simple 1 & Simple 2"
}
},
{
id: "2",
league: {
name: "Senegal Ligue 2",
team: "Simple"
}
},
{
id: "3",
league: {
name: "World Club Friendlies",
team: "Simple 3 & Simple 4"
}
},
]
The First and Third league names are similar.
The above code output looks like this:
League Name: World Club Friendlies / Team: Simple 1 & Simple 2
League Name: Senegal Ligue 2 / Team: Simple
League Name: World Club Friendlies / Team: Simple 3 & Simple 4
Now i need to print following result:
League Name: World Club Friendlies / Team: Simple 1 & Simple 2 & Simple 3 & Simple 4
League Name: Senegal Ligue 2 / Team: Simple
I have somthing like this code:
foreach($content as $result){
echo $result['league']['name'];
echo $result['team'];
}
Use reduce and check for team name as key and apply the condition that you want as follows:
var data = [{
id: "1",
league: {
name: "World Club Friendlies",
team: "Simple 1 & Simple 2"
}
},
{
id: "2",
league: {
name: "Senegal Ligue 2",
team: "Simple"
}
},
{
id: "3",
league: {
name: "World Club Friendlies",
team: "Simple 3 & Simple 4"
}
},
]
var res = data.reduce((acc, curr) => {
if (acc[curr.league.name]) {
acc[curr.league.name] = {
name: curr.league.name,
team: acc[curr.league.name].team + " & " + curr.league.team
}
} else {
acc[curr.league.name] = {
name: curr.league.name,
team: curr.league.team
}
}
return acc;
}, {});
for (data in res) {
console.log("League name: " + res[data].name + "/Team:" + res[data].team)
}

Swift 5 group and split array of objects based on object value

I have a sorted array
let things = [
Thing(activity: "1", name: "value1"),
Thing(activity: "1", name: "value2"),
Thing(activity: "1", name: "value3"),
Thing(activity: "2", name: "value4"),
Thing(activity: "2", name: "value5"),
Thing(activity: "3", name: "value6"),
Thing(activity: "3", name: "value7"),
Thing(activity: "1", name: "value8"),
Thing(activity: "1", name: "value9"),
Thing(activity: "1", name: "value10")
]
I would like to produce array of arrays splitted when the activity value changes similar to the following
[[Thing(activity: "1", name: "value1"),
Thing(activity: "1", name: "value2"),
Thing(activity: "1", name: "value3")],
[Thing(activity: "2", name: "value4"),
Thing(activity: "2", name: "value5")],
[Thing(activity: "3", name: "value6"),
Thing(activity: "3", name: "value7")],
[Thing(activity: "1", name: "value8"),
Thing(activity: "1", name: "value9"),
Thing(activity: "1", name: "value10")]]
A generalized solution would be:
extension Sequence {
func grouped<T: Equatable>(by block: (Element) throws -> T) rethrows -> [[Element]] {
return try reduce(into: []) { result, element in
if let lastElement = result.last?.last, try block(lastElement) == block(element) {
result[result.index(before: result.endIndex)].append(element)
} else {
result.append([element])
}
}
}
}
Then you can do:
let results = things.grouped { $0.activity }
A less elegant (but slightly more efficient) solution would be:
extension Sequence {
func grouped<T: Equatable>(by block: (Element) throws -> T) rethrows -> [[Element]] {
var results: [[Element]] = []
var lastValue: T?
var index = results.endIndex
for element in self {
let value = try block(element)
if let lastValue = lastValue, lastValue == value {
results[index].append(element)
} else {
results.append([element])
index = results.index(before: results.endIndex)
lastValue = value
}
}
return results
}
}
As already mentioned by #matt in comments you can use collection method reduce(into:) to group your elements by checking if the activity of the last element of the last array is equal to the current element activity, if so just append a new element to the last array, otherwise append a new array with a single element to the outer array:
struct Thing {
let activity, name: String
}
let things: [Thing] = [
.init(activity: "1", name: "value1"),
.init(activity: "1", name: "value2"),
.init(activity: "1", name: "value3"),
.init(activity: "2", name: "value4"),
.init(activity: "2", name: "value5"),
.init(activity: "3", name: "value6"),
.init(activity: "3", name: "value7"),
.init(activity: "1", name: "value8"),
.init(activity: "1", name: "value9"),
.init(activity: "1", name: "value10")]
let grouped: [[Thing]] = things.reduce(into: []) {
$0.last?.last?.activity == $1.activity ?
$0[$0.index(before: $0.endIndex)].append($1) :
$0.append([$1])
}
print(grouped) // "[[__lldb_expr_1.Thing(activity: "1", name: "value1"), __lldb_expr_1.Thing(activity: "1", name: "value2"), __lldb_expr_1.Thing(activity: "1", name: "value3")], [__lldb_expr_1.Thing(activity: "2", name: "value4"), __lldb_expr_1.Thing(activity: "2", name: "value5")], [__lldb_expr_1.Thing(activity: "3", name: "value6"), __lldb_expr_1.Thing(activity: "3", name: "value7")], [__lldb_expr_1.Thing(activity: "1", name: "value8"), __lldb_expr_1.Thing(activity: "1", name: "value9"), __lldb_expr_1.Thing(activity: "1", name: "value10")]]\n"

Resources