Swift: Как отфильтровать массив объектов по необходимому количеству значений? - PullRequest
0 голосов
/ 03 августа 2020

У меня есть такой класс:

class JobMembers {
    
    var key: String?
    let memberJob: String?
    let memberName: String?
    let memberID:String?
    let normalPrice:Double?
    var sumFreelanceRating:Double!
    let priceJPerfScore:Double?
    
        
    
    init(sumFreelanceRating:Double, normalPrice:Double, memberJob: String, memberName: String, priceJPerfScore:Double, memberID:String) {
            
        self.sumFreelanceRating = sumFreelanceRating
        self.normalPrice = normalPrice
        self.memberName = memberName
        self.memberJob = memberJob
        self.priceJPerfScore = priceJPerfScore
        self.memberID = memberID
  
        }
    
    
    var dictValue: [String: Any] {
        
        return ["memberName" : memberName,
                "memberJob" : memberJob,
                "normalPrice": normalPrice,
                "sumFreelanceRating" : sumFreelanceRating,
                "priceJPerfScore": priceJPerfScore,
                "memberID": memberID]
    }
   
}

и инициализирую массив и заполняю его для целей тестирования следующим образом:

var freelancerArray = [JobMembers]()

var member1JP = JobMembers(sumFreelanceRating: 35.6, normalPrice: 4.4, memberJob: "Tennis", memberName: "Aggazzi", priceJPerfScore: 2.2, memberID: "-FG84832iMV0Seznf-D" )

var member2JP = JobMembers(ajp: 2.3, crea: 3.4, ijr: 4.5, qpa: 5.6, coj: 6.7, los: 1.3, iracc: 2.4, dph: 4.8, sumFreelanceRating: 31.0, normalPrice: 6.84, memberJob: "Fussball", memberName: "Mueller", priceJPerfScore: 172.0, memberID: "-MA6VScOQiMV0Seznf-D")

var member3JP = JobMembers(sumFreelanceRating: 41.9, normalPrice: 5.5, memberJob: "Fussball", memberName: "Schweinsteiger", priceJPerfScore: 140.0, memberID: "-FF6666QiMV0Seznf-D")

var member4JP = JobMembers(sumFreelanceRating: 38.7, normalPrice: 3.3, memberJob: "Tennis", memberName: "Federer", priceJPerfScore: 170.0, memberID: "-FA874506QiMV0Seznf-D")

var member5JP = JobMembers(sumFreelanceRating: 36.7, normalPrice: 5.3, memberJob: "Tennis", memberName: "Becker", priceJPerfScore: 125.0, memberID: "-FE3454506QiMV0Seznf-D")

var member6JP = JobMembers(sumFreelanceRating: 32.5, normalPrice: 4.4, memberJob: "Tennis", memberName: "Williams", priceJPerfScore: 4.2, memberID: "-ADE3344506QiMV0Seznf-D")

var member7JP = JobMembers(sumFreelanceRating: 37.6, normalPrice: 2.8, memberJob: "Fussball", memberName: "Woods", priceJPerfScore: 5.8, memberID: "-GHI4564506QiMV0Seznf-D")

var member8JP = JobMembers(sumFreelanceRating: 36.6, normalPrice: 4.4, memberJob: "Golf", memberName: "Spieth", priceJPerfScore: 4.4, memberID: "-FGI4564506QiMV0Seznf-D")

var member9JP = JobMembers(sumFreelanceRating: 28.09, normalPrice: 2.8, memberJob: "Skate", memberName: "Dixon", priceJPerfScore: 2.8, memberID: "-4204564506QiMV0Seznf-D")
freelancerArray.append(member1JP)
freelancerArray.append(member2JP)
freelancerArray.append(member3JP)
freelancerArray.append(member4JP)
freelancerArray.append(member5JP)
freelancerArray.append(member6JP)
freelancerArray.append(member7JP)
freelancerArray.append(member8JP)
freelancerArray.append(member9JP)

У меня есть другой класс, который представляет пользователей выбор, сколько members ему нужно, из указанного c memberJob:

class JobAmount {
    var key: String?
    let jobName: String?
    let jobAmount: Int?
    
    init(jobName: String, jobAmount: Int) {
        self.jobName = jobName
        self.jobAmount = jobAmount
    }
    var dictValue: [String: Any] {
    
    return ["jobName" : jobName,
            "jobAmount" : jobAmount ]
        
    }
}

В целях тестирования я заполнил массив следующим образом:

var jobsNeeded:[JobAmount] = []

var jobNeeded1 = JobAmount(jobName: Tennis, jobAmount:3)
var jobNeeded2 = JobAmount(jobName: Fussball, jobAmount2


Чего я хочу достичь с помощью этого?

Цель должна состоять в том, чтобы заполнить массив, который имеет следующие требования:

  • Для требуемых jobAmount соответствующих JobNames, добавьте members в новый массив, который имеет максимальное значение sumFreelanceRating для требуемого JobName.

Мой подход на данный момент

Я пробовал разные решения на этом форуме, поискал быструю документацию и c. но я не смог найти подходящее решение.

Я предполагаю, что хороший способ go:

(1) отсортировать freelancerArray как показано ниже: freelancerArray.sort(by: {$0.sumFreelanceRating > $1.sumFreelanceRating})

(2) Отфильтруйте freelancerArray в temporaryArray, содержащем только объекты для указанных c memberJob

(3) Добавьте количество необходимых значений в окончательный массив (for i in 0..<jobName.jobAmount, что-то вроде JobRequirementArray, где будут сохранены все members, которые необходимы.

Для Шага 2 и 3 это, очевидно, должно быть выполнено для каждого memberJob, необходимого пользователю. Какое и сколько memberJobs это будет, заранее неизвестно.

Изменить желаемый результат:

let finalJobsneeded:[JobMembers]()

Тогда массив должен содержать следующие члены JobMembers:

finalJobsneeded = [member1JP, member3JP, member4JP, member5JP, member7JP]

Как видите, нам нужно всего 5 членов, причем 2 из них должны содержать memberJob: Fussball, а также иметь максимальное значение sumFreelanceRating для всех альтернатив memberJob: Fussball. Остальные 3 члена должны содержать memberJob: Tennis а также га имеет наивысшее значение для всех альтернатив memberJob: Tennis

. Надеюсь, мое объяснение моей маленькой проблемы было достаточно ясным и кто-то мог помочь мне воплотить мои идеи в реальный код!

Спасибо за вашу помощь все :)

Ответы [ 2 ]

1 голос
/ 03 августа 2020

Сначала создайте словарь для хранения выбранных элементов

var selected = [String: [JobMembers]]()

Затем используйте forEach l oop, чтобы отфильтровать элементы с правильным именем задания. Поскольку это выполняется для каждого задания, мы можем одновременно сортировать и выбирать только необходимое число.

jobsNeeded.forEach { job in
    selected[job.jobName, default: []].append(contentsOf:
        freelancerArray
            .filter { job.jobName == $0.memberJob}
            .sorted { member1, member2 in member1.sumFreelanceRating > member2.sumFreelanceRating}
            .prefix(job.jobAmount)
    )
}

Если вы хотите, чтобы все элементы в одном массиве, вы можете использовать flatMap для значений словаря

let selectedMembers = selected.values.flatMap({$0})
0 голосов
/ 03 августа 2020

На случай, если кто-то пытается добиться того же. У меня это работает сейчас!

func tryToGetIt() {
 var temp1: [JobMembers] = []
    for jobAmount in jobAmountArray{
        temp1 = freelancerArray.filter { $0.memberJob == jobAmount.jobName}
        temp1.sort(by: {$0.sumFreelanceRating > $1.sumFreelanceRating})
        for value in temp1{
            print("temp1: ")
            print(value.memberName as Any)
        }
        let neededValue = jobAmount.jobAmount
        print("needed Value: ", neededValue as Any, "for Job: ", jobAmount.jobName as Any)
        let deletValue = temp1.count - neededValue!
        print("delet Value: ", deletValue)
        temp1.remove(0..<deletValue)
        
        for member in temp1 {
            print("memberName: ", member.memberName as Any, "memberJob: ", member.memberJob as Any, "memberID: ", member.memberID  as Any, "memberJP: " as Any, member.sumFreelanceRating as Any)
        }
        print(temp1.count)
        
            
        for value in temp1 {
            finalBest.append(value)
        }
        
        print("\n \n")
    }
    for member in finalBest {
        print("memberName: ", member.memberName as Any, "memberJob: ", member.memberJob  as Any, "memberID: " as Any, member.memberID as Any, "memberJP: ", member.sumFreelanceRating as Any)
        print(finalBest.count)
    }
    print("final Best: ", finalBest)
    print("final Best amount: ", finalBest.count)
}

...